fix_boost_mpl_preprocess.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. # Copyright Deniz Bahadir 2015
  2. #
  3. # Distributed under the Boost Software License, Version 1.0.
  4. # (See accompanying file LICENSE_1_0.txt or copy at
  5. # http://www.boost.org/LICENSE_1_0.txt)
  6. #
  7. # See http://www.boost.org/libs/mpl for documentation.
  8. # See http://stackoverflow.com/a/29627158/3115457 for further information.
  9. import argparse
  10. import sys
  11. import os.path
  12. import re
  13. import fileinput
  14. import datetime
  15. import glob
  16. def check_header_comment(filename):
  17. """Checks if the header-comment of the given file needs fixing."""
  18. # Check input file.
  19. name = os.path.basename( filename )
  20. # Read content of input file.
  21. sourcefile = open( filename, "rU" )
  22. content = sourcefile.read()
  23. sourcefile.close()
  24. # Search content for '$Id$'.
  25. match = re.search(r'\$Id\$', content)
  26. if match == None:
  27. # Make sure that the correct value for '$Id$' was already set.
  28. match = re.search(r'\$Id: ' + name + r'\s+[^$]+\$', content)
  29. if match != None:
  30. # The given file needs no fixing.
  31. return False
  32. # The given file needs fixing.
  33. return True
  34. def check_input_files_for_variadic_seq(headerDir, sourceDir):
  35. """Checks if files, used as input when pre-processing MPL-containers in their variadic form, need fixing."""
  36. # Check input files in include/source-directories.
  37. files = glob.glob( os.path.join( headerDir, "*.hpp" ) )
  38. files += glob.glob( os.path.join( headerDir, "aux_", "*.hpp" ) )
  39. files += glob.glob( os.path.join( sourceDir, "src", "*" ) )
  40. for currentFile in sorted( files ):
  41. if check_header_comment( currentFile ):
  42. return True
  43. return False
  44. def check_input_files_for_numbered_seq(sourceDir, suffix, containers):
  45. """Check if files, used as input when pre-processing MPL-containers in their numbered form, need fixing."""
  46. # Check input files for each MPL-container type.
  47. for container in containers:
  48. files = glob.glob( os.path.join( sourceDir, container, container + '*' + suffix ) )
  49. for currentFile in sorted( files ):
  50. if check_header_comment( currentFile ):
  51. return True
  52. return False
  53. def check_input_files(headerDir, sourceDir, containers=['vector', 'list', 'set', 'map'],
  54. seqType='both', verbose=False):
  55. """Checks if source- and header-files, used as input when pre-processing MPL-containers, need fixing."""
  56. # Check the input files for containers in their variadic form.
  57. result1 = False
  58. if seqType == "both" or seqType == "variadic":
  59. if verbose:
  60. print "Check if input files for pre-processing Boost.MPL variadic containers need fixing."
  61. result1 = check_input_files_for_variadic_seq(headerDir, sourceDir)
  62. if verbose:
  63. if result1:
  64. print " At least one input file needs fixing!"
  65. else:
  66. print " No input file needs fixing!"
  67. # Check the input files for containers in their numbered form.
  68. result2 = False
  69. result3 = False
  70. if seqType == "both" or seqType == "numbered":
  71. if verbose:
  72. print "Check input files for pre-processing Boost.MPL numbered containers."
  73. result2 = check_input_files_for_numbered_seq(headerDir, ".hpp", containers)
  74. result3 = check_input_files_for_numbered_seq(sourceDir, ".cpp", containers)
  75. if verbose:
  76. if result2 or result3:
  77. print " At least one input file needs fixing!"
  78. else:
  79. print " No input file needs fixing!"
  80. # Return result.
  81. return result1 or result2 or result3
  82. def fix_header_comment(filename, timestamp):
  83. """Fixes the header-comment of the given file."""
  84. # Fix input file.
  85. name = os.path.basename( filename )
  86. for line in fileinput.input( filename, inplace=1, mode="rU" ):
  87. # If header-comment already contains anything for '$Id$', remove it.
  88. line = re.sub(r'\$Id:[^$]+\$', r'$Id$', line.rstrip())
  89. # Replace '$Id$' by a string containing the file's name (and a timestamp)!
  90. line = re.sub(re.escape(r'$Id$'), r'$Id: ' + name + r' ' + timestamp.isoformat() + r' $', line.rstrip())
  91. print(line)
  92. def fix_input_files_for_variadic_seq(headerDir, sourceDir, timestamp):
  93. """Fixes files used as input when pre-processing MPL-containers in their variadic form."""
  94. # Fix files in include/source-directories.
  95. files = glob.glob( os.path.join( headerDir, "*.hpp" ) )
  96. files += glob.glob( os.path.join( headerDir, "aux_", "*.hpp" ) )
  97. files += glob.glob( os.path.join( sourceDir, "src", "*" ) )
  98. for currentFile in sorted( files ):
  99. fix_header_comment( currentFile, timestamp )
  100. def fix_input_files_for_numbered_seq(sourceDir, suffix, timestamp, containers):
  101. """Fixes files used as input when pre-processing MPL-containers in their numbered form."""
  102. # Fix input files for each MPL-container type.
  103. for container in containers:
  104. files = glob.glob( os.path.join( sourceDir, container, container + '*' + suffix ) )
  105. for currentFile in sorted( files ):
  106. fix_header_comment( currentFile, timestamp )
  107. def fix_input_files(headerDir, sourceDir, containers=['vector', 'list', 'set', 'map'],
  108. seqType='both', verbose=False):
  109. """Fixes source- and header-files used as input when pre-processing MPL-containers."""
  110. # The new modification time.
  111. timestamp = datetime.datetime.now();
  112. # Fix the input files for containers in their variadic form.
  113. if seqType == "both" or seqType == "variadic":
  114. if verbose:
  115. print "Fix input files for pre-processing Boost.MPL variadic containers."
  116. fix_input_files_for_variadic_seq(headerDir, sourceDir, timestamp)
  117. # Fix the input files for containers in their numbered form.
  118. if seqType == "both" or seqType == "numbered":
  119. if verbose:
  120. print "Fix input files for pre-processing Boost.MPL numbered containers."
  121. fix_input_files_for_numbered_seq(headerDir, ".hpp", timestamp, containers)
  122. fix_input_files_for_numbered_seq(sourceDir, ".cpp", timestamp, containers)
  123. def to_existing_absolute_path(string):
  124. """Converts a path into its absolute path and verifies that it exists or throws an exception."""
  125. value = os.path.abspath(string)
  126. if not os.path.exists( value ) or not os.path.isdir( value ):
  127. msg = '"%r" is not a valid path to a directory.' % string
  128. raise argparse.ArgumentTypeError(msg)
  129. return value
  130. def main():
  131. """The main function."""
  132. # Prepare and run cmdline-parser.
  133. cmdlineParser = argparse.ArgumentParser(
  134. description="Fixes the input files used for pre-processing of Boost.MPL headers.")
  135. cmdlineParser.add_argument("-v", "--verbose", dest='verbose', action='store_true',
  136. help="Be a little bit more verbose.")
  137. cmdlineParser.add_argument("--check-only", dest='checkonly', action='store_true',
  138. help="Only checks if fixing is required.")
  139. cmdlineParser.add_argument(dest='sourceDir', metavar="<source-dir>",
  140. type=to_existing_absolute_path,
  141. help="The source-directory of Boost.")
  142. args = cmdlineParser.parse_args()
  143. # Some verbose debug output.
  144. if args.verbose:
  145. print "Arguments extracted from command-line:"
  146. print " verbose = ", args.verbose
  147. print " check-only = ", args.checkonly
  148. print " source directory = ", args.sourceDir
  149. # The directories for header- and source files of Boost.MPL.
  150. # NOTE: Assuming 'args.sourceDir' is the source-directory of the entire boost project.
  151. headerDir = os.path.join( args.sourceDir, "boost", "mpl" )
  152. sourceDir = os.path.join( args.sourceDir, "libs", "mpl", "preprocessed" )
  153. # Check that the header/source-directories exist.
  154. if not os.path.exists( headerDir ) or not os.path.exists( sourceDir ):
  155. # Maybe 'args.sourceDir' is not the source-directory of the entire boost project
  156. # but instead of the Boost.MPL git-directory, only?
  157. headerDir = os.path.join( args.sourceDir, "include", "boost", "mpl" )
  158. sourceDir = os.path.join( args.sourceDir, "preprocessed" )
  159. if not os.path.exists( headerDir ) or not os.path.exists( sourceDir ):
  160. cmdlineParser.print_usage()
  161. print "error: Cannot find Boost.MPL header/source files in given Boost source-directory!"
  162. sys.exit(0)
  163. # Some verbose debug output.
  164. if args.verbose:
  165. print "Chosen header-directory: ", headerDir
  166. print "Chosen source-directory: ", sourceDir
  167. if args.checkonly:
  168. # Check input files for generating pre-processed headers.
  169. result = check_input_files(headerDir, sourceDir, verbose = args.verbose)
  170. if result:
  171. print "Fixing the input-files used for pre-processing of Boost.MPL headers IS required."
  172. else:
  173. print "Fixing the input-files used for pre-processing of Boost.MPL headers is NOT required."
  174. else:
  175. # Fix input files for generating pre-processed headers.
  176. fix_input_files(headerDir, sourceDir, verbose = args.verbose)
  177. if __name__ == '__main__':
  178. main()