Martin Hořeňovský | 8115983 | 2017-01-20 12:28:40 +0100 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
Phil Nash | 1f71d1f | 2017-02-15 11:54:47 +0000 | [diff] [blame] | 3 | from __future__ import print_function |
Martin Moene | 77c9edf | 2014-03-08 11:31:38 +0100 | [diff] [blame] | 4 | |
Phil Nash | 7673a30 | 2012-11-15 22:15:41 +0000 | [diff] [blame] | 5 | import os |
| 6 | import sys |
| 7 | import re |
| 8 | import datetime |
Phil Nash | c4a089c | 2013-12-03 18:52:41 +0000 | [diff] [blame] | 9 | import string |
Martin Hořeňovský | 93f84b5 | 2017-07-09 20:58:51 +0200 | [diff] [blame] | 10 | from glob import glob |
Phil Nash | 7673a30 | 2012-11-15 22:15:41 +0000 | [diff] [blame] | 11 | |
Phil Nash | 2278451 | 2013-04-24 18:58:57 +0100 | [diff] [blame] | 12 | from scriptCommon import catchPath |
| 13 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 14 | def generate(v): |
| 15 | includesParser = re.compile( r'\s*#\s*include\s*"(.*)"' ) |
| 16 | guardParser = re.compile( r'\s*#.*(TWOBLUECUBES_)?CATCH_.*_INCLUDED') |
| 17 | defineParser = re.compile( r'\s*#define\s+(TWOBLUECUBES_)?CATCH_.*_INCLUDED') |
| 18 | ifParser = re.compile( r'\s*#ifndef (TWOBLUECUBES_)?CATCH_.*_INCLUDED') |
| 19 | endIfParser = re.compile( r'\s*#endif // (TWOBLUECUBES_)?CATCH_.*_INCLUDED') |
| 20 | ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' ) |
| 21 | commentParser1 = re.compile( r'^\s*/\*') |
| 22 | commentParser2 = re.compile( r'^ \*') |
| 23 | blankParser = re.compile( r'^\s*$') |
Phil Nash | 21f7ef6 | 2015-06-29 18:05:23 +0100 | [diff] [blame] | 24 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 25 | seenHeaders = set([]) |
| 26 | rootPath = os.path.join( catchPath, 'include/' ) |
| 27 | outputPath = os.path.join( catchPath, 'single_include/catch.hpp' ) |
Martin Hořeňovský | 93f84b5 | 2017-07-09 20:58:51 +0200 | [diff] [blame] | 28 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 29 | globals = { |
| 30 | 'includeImpl' : True, |
| 31 | 'ifdefs' : 0, |
| 32 | 'implIfDefs' : -1 |
| 33 | } |
Phil Nash | 7673a30 | 2012-11-15 22:15:41 +0000 | [diff] [blame] | 34 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 35 | for arg in sys.argv[1:]: |
| 36 | arg = string.lower(arg) |
| 37 | if arg == "noimpl": |
| 38 | globals['includeImpl'] = False |
| 39 | print( "Not including impl code" ) |
Phil Nash | de49ec4 | 2013-12-04 20:25:14 +0000 | [diff] [blame] | 40 | else: |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 41 | print( "\n** Unrecognised argument: " + arg + " **\n" ) |
| 42 | exit(1) |
Phil Nash | 7673a30 | 2012-11-15 22:15:41 +0000 | [diff] [blame] | 43 | |
Phil Nash | 7673a30 | 2012-11-15 22:15:41 +0000 | [diff] [blame] | 44 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 45 | # ensure that the output directory exists (hopefully no races) |
| 46 | outDir = os.path.dirname(outputPath) |
| 47 | if not os.path.exists(outDir): |
| 48 | os.makedirs(outDir) |
| 49 | out = open( outputPath, 'w' ) |
Phil Nash | 7673a30 | 2012-11-15 22:15:41 +0000 | [diff] [blame] | 50 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 51 | def write( line ): |
| 52 | if globals['includeImpl'] or globals['implIfDefs'] == -1: |
| 53 | out.write( line ) |
Phil Nash | 7673a30 | 2012-11-15 22:15:41 +0000 | [diff] [blame] | 54 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 55 | def insertCpps(): |
| 56 | dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters']] |
| 57 | cppFiles = [] |
| 58 | for dir in dirs: |
| 59 | cppFiles += glob(os.path.join(dir, '*.cpp')) |
Martin Hořeňovský | 46e2879 | 2017-08-30 15:42:23 +0200 | [diff] [blame] | 60 | # To minimize random diffs, sort the files before processing them |
| 61 | for fname in sorted(cppFiles): |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 62 | dir, name = fname.rsplit(os.path.sep, 1) |
| 63 | dir += os.path.sep |
| 64 | parseFile(dir, name) |
Phil Nash | 0c90ab3 | 2012-11-16 20:43:27 +0000 | [diff] [blame] | 65 | |
Martin Hořeňovský | dee61df | 2017-08-24 21:59:06 +0200 | [diff] [blame] | 66 | def parseFile( path, filename ): |
| 67 | f = open( os.path.join(path, filename), 'r' ) |
| 68 | blanks = 0 |
| 69 | write( "// start {0}\n".format( filename ) ) |
| 70 | for line in f: |
| 71 | if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line: |
| 72 | insertCpps() |
| 73 | continue |
| 74 | elif ifParser.match( line ): |
| 75 | globals['ifdefs'] += 1 |
| 76 | elif endIfParser.match( line ): |
| 77 | globals['ifdefs'] -= 1 |
| 78 | if globals['ifdefs'] == globals['implIfDefs']: |
| 79 | globals['implIfDefs'] = -1 |
| 80 | m = includesParser.match( line ) |
| 81 | if m: |
| 82 | header = m.group(1) |
| 83 | headerPath, sep, headerFile = header.rpartition( "/" ) |
| 84 | if not headerFile in seenHeaders: |
| 85 | if headerFile != "tbc_text_format.h" and headerFile != "clara.h": |
| 86 | seenHeaders.add( headerFile ) |
| 87 | if headerPath == "internal" and path.endswith("internal/"): |
| 88 | headerPath = "" |
| 89 | sep = "" |
| 90 | if os.path.exists( path + headerPath + sep + headerFile ): |
| 91 | parseFile( path + headerPath + sep, headerFile ) |
| 92 | else: |
| 93 | parseFile( rootPath + headerPath + sep, headerFile ) |
| 94 | else: |
| 95 | if ifImplParser.match(line): |
| 96 | globals['implIfDefs'] = globals['ifdefs'] |
| 97 | if (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ): |
| 98 | if blankParser.match( line ): |
| 99 | blanks = blanks + 1 |
| 100 | else: |
| 101 | blanks = 0 |
| 102 | if blanks < 2 and not defineParser.match(line): |
| 103 | write( line.rstrip() + "\n" ) |
| 104 | write( '// end {}\n'.format(filename) ) |
| 105 | |
| 106 | |
| 107 | out.write( "/*\n" ) |
| 108 | out.write( " * Catch v{0}\n".format( v.getVersionString() ) ) |
| 109 | out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) ) |
| 110 | out.write( " * ----------------------------------------------------------\n" ) |
| 111 | out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" ) |
| 112 | out.write( " * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) ) |
| 113 | out.write( " *\n" ) |
| 114 | out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" ) |
| 115 | out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" ) |
| 116 | out.write( " */\n" ) |
| 117 | out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) |
| 118 | out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) |
| 119 | |
| 120 | parseFile( rootPath, 'catch.hpp' ) |
| 121 | |
| 122 | out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" ) |
| 123 | out.close() |
| 124 | print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) ) |
| 125 | |
| 126 | |
| 127 | if __name__ == '__main__': |
| 128 | from releaseCommon import Version |
| 129 | generate(Version()) |