1*4d6fc14bSjoerg#!/usr/bin/env python 2*4d6fc14bSjoerg 3*4d6fc14bSjoergimport glob 4*4d6fc14bSjoergimport os 5*4d6fc14bSjoergimport posixpath 6*4d6fc14bSjoergimport re 7*4d6fc14bSjoerg 8*4d6fc14bSjoerg 9*4d6fc14bSjoergdef get_libcxx_paths(): 10*4d6fc14bSjoerg utils_path = os.path.dirname(os.path.abspath(__file__)) 11*4d6fc14bSjoerg script_name = os.path.basename(__file__) 12*4d6fc14bSjoerg assert os.path.exists(utils_path) 13*4d6fc14bSjoerg src_root = os.path.dirname(utils_path) 14*4d6fc14bSjoerg include_path = os.path.join(src_root, 'include') 15*4d6fc14bSjoerg assert os.path.exists(include_path) 16*4d6fc14bSjoerg libcxx_test_path = os.path.join(src_root, 'test', 'libcxx') 17*4d6fc14bSjoerg assert os.path.exists(libcxx_test_path) 18*4d6fc14bSjoerg return script_name, src_root, include_path, libcxx_test_path 19*4d6fc14bSjoerg 20*4d6fc14bSjoerg 21*4d6fc14bSjoergscript_name, source_root, include_path, libcxx_test_path = get_libcxx_paths() 22*4d6fc14bSjoerg 23*4d6fc14bSjoergheader_markup = { 24*4d6fc14bSjoerg "atomic": ["ifndef _LIBCPP_HAS_NO_THREADS"], 25*4d6fc14bSjoerg "barrier": ["ifndef _LIBCPP_HAS_NO_THREADS"], 26*4d6fc14bSjoerg "future": ["ifndef _LIBCPP_HAS_NO_THREADS"], 27*4d6fc14bSjoerg "latch": ["ifndef _LIBCPP_HAS_NO_THREADS"], 28*4d6fc14bSjoerg "mutex": ["ifndef _LIBCPP_HAS_NO_THREADS"], 29*4d6fc14bSjoerg "shared_mutex": ["ifndef _LIBCPP_HAS_NO_THREADS"], 30*4d6fc14bSjoerg "semaphore": ["ifndef _LIBCPP_HAS_NO_THREADS"], 31*4d6fc14bSjoerg "thread": ["ifndef _LIBCPP_HAS_NO_THREADS"], 32*4d6fc14bSjoerg 33*4d6fc14bSjoerg "filesystem": ["ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY"], 34*4d6fc14bSjoerg "experimental/filesystem": ["ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY"], 35*4d6fc14bSjoerg 36*4d6fc14bSjoerg "clocale": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 37*4d6fc14bSjoerg "codecvt": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 38*4d6fc14bSjoerg "fstream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 39*4d6fc14bSjoerg "iomanip": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 40*4d6fc14bSjoerg "ios": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 41*4d6fc14bSjoerg "iostream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 42*4d6fc14bSjoerg "istream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 43*4d6fc14bSjoerg "locale": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 44*4d6fc14bSjoerg "locale.h": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 45*4d6fc14bSjoerg "ostream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 46*4d6fc14bSjoerg "regex": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 47*4d6fc14bSjoerg "sstream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 48*4d6fc14bSjoerg "streambuf": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 49*4d6fc14bSjoerg "strstream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 50*4d6fc14bSjoerg 51*4d6fc14bSjoerg "experimental/coroutine": ["if defined(__cpp_coroutines)"], 52*4d6fc14bSjoerg "experimental/regex": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"], 53*4d6fc14bSjoerg} 54*4d6fc14bSjoerg 55*4d6fc14bSjoergallowed_extensions = ['', '.h'] 56*4d6fc14bSjoergindent_width = 4 57*4d6fc14bSjoerg 58*4d6fc14bSjoerg 59*4d6fc14bSjoergbegin_pattern = """\ 60*4d6fc14bSjoerg//////////////////////////////////////////////////////////////////////////////// 61*4d6fc14bSjoerg// BEGIN-GENERATED-HEADERS 62*4d6fc14bSjoerg//////////////////////////////////////////////////////////////////////////////// 63*4d6fc14bSjoerg""" 64*4d6fc14bSjoerg 65*4d6fc14bSjoergwarning_note = """\ 66*4d6fc14bSjoerg// WARNING: This test was generated by {script_name} 67*4d6fc14bSjoerg// and should not be edited manually. 68*4d6fc14bSjoerg 69*4d6fc14bSjoerg""".format(script_name=script_name) 70*4d6fc14bSjoerg 71*4d6fc14bSjoergend_pattern = """\ 72*4d6fc14bSjoerg//////////////////////////////////////////////////////////////////////////////// 73*4d6fc14bSjoerg// END-GENERATED-HEADERS 74*4d6fc14bSjoerg//////////////////////////////////////////////////////////////////////////////// 75*4d6fc14bSjoerg""" 76*4d6fc14bSjoerg 77*4d6fc14bSjoerggenerated_part_pattern = re.compile(re.escape(begin_pattern) + ".*" + re.escape(end_pattern), 78*4d6fc14bSjoerg re.MULTILINE | re.DOTALL) 79*4d6fc14bSjoerg 80*4d6fc14bSjoergheaders_template = """\ 81*4d6fc14bSjoerg// Top level headers 82*4d6fc14bSjoerg{top_level_headers} 83*4d6fc14bSjoerg 84*4d6fc14bSjoerg// experimental headers 85*4d6fc14bSjoerg#if __cplusplus >= 201103L 86*4d6fc14bSjoerg{experimental_headers} 87*4d6fc14bSjoerg#endif // __cplusplus >= 201103L 88*4d6fc14bSjoerg 89*4d6fc14bSjoerg// extended headers 90*4d6fc14bSjoerg{extended_headers} 91*4d6fc14bSjoerg""" 92*4d6fc14bSjoerg 93*4d6fc14bSjoerg 94*4d6fc14bSjoergdef should_keep_header(p, exclusions=None): 95*4d6fc14bSjoerg if os.path.isdir(p): 96*4d6fc14bSjoerg return False 97*4d6fc14bSjoerg 98*4d6fc14bSjoerg if exclusions: 99*4d6fc14bSjoerg relpath = os.path.relpath(p, include_path) 100*4d6fc14bSjoerg relpath = posixpath.join(*os.path.split(relpath)) 101*4d6fc14bSjoerg if relpath in exclusions: 102*4d6fc14bSjoerg return False 103*4d6fc14bSjoerg 104*4d6fc14bSjoerg return os.path.splitext(p)[1] in allowed_extensions 105*4d6fc14bSjoerg 106*4d6fc14bSjoerg 107*4d6fc14bSjoergdef produce_include(relpath, indent_level, post_include=None): 108*4d6fc14bSjoerg relpath = posixpath.join(*os.path.split(relpath)) 109*4d6fc14bSjoerg template = "{preambule}#{indentation}include <{include}>{post_include}{postambule}" 110*4d6fc14bSjoerg 111*4d6fc14bSjoerg base_indentation = ' '*(indent_width * indent_level) 112*4d6fc14bSjoerg next_indentation = base_indentation + ' '*(indent_width) 113*4d6fc14bSjoerg post_include = "\n{}".format(post_include) if post_include else '' 114*4d6fc14bSjoerg 115*4d6fc14bSjoerg markup = header_markup.get(relpath, None) 116*4d6fc14bSjoerg if markup: 117*4d6fc14bSjoerg preambule = '#{indentation}{directive}\n'.format( 118*4d6fc14bSjoerg directive=markup[0], 119*4d6fc14bSjoerg indentation=base_indentation, 120*4d6fc14bSjoerg ) 121*4d6fc14bSjoerg postambule = '\n#{indentation}endif'.format( 122*4d6fc14bSjoerg indentation=base_indentation, 123*4d6fc14bSjoerg ) 124*4d6fc14bSjoerg indentation = next_indentation 125*4d6fc14bSjoerg else: 126*4d6fc14bSjoerg preambule = '' 127*4d6fc14bSjoerg postambule = '' 128*4d6fc14bSjoerg indentation = base_indentation 129*4d6fc14bSjoerg 130*4d6fc14bSjoerg return template.format( 131*4d6fc14bSjoerg include=relpath, 132*4d6fc14bSjoerg post_include=post_include, 133*4d6fc14bSjoerg preambule=preambule, 134*4d6fc14bSjoerg postambule=postambule, 135*4d6fc14bSjoerg indentation=indentation, 136*4d6fc14bSjoerg ) 137*4d6fc14bSjoerg 138*4d6fc14bSjoerg 139*4d6fc14bSjoergdef produce_headers(path_parts, indent_level, post_include=None, exclusions=None): 140*4d6fc14bSjoerg pattern = os.path.join(*path_parts, '[a-z]*') 141*4d6fc14bSjoerg 142*4d6fc14bSjoerg files = sorted(glob.glob(pattern, recursive=False)) 143*4d6fc14bSjoerg 144*4d6fc14bSjoerg include_headers = [ 145*4d6fc14bSjoerg produce_include(os.path.relpath(p, include_path), 146*4d6fc14bSjoerg indent_level, post_include=post_include) 147*4d6fc14bSjoerg for p in files 148*4d6fc14bSjoerg if should_keep_header(p, exclusions) 149*4d6fc14bSjoerg ] 150*4d6fc14bSjoerg 151*4d6fc14bSjoerg return '\n'.join(include_headers) 152*4d6fc14bSjoerg 153*4d6fc14bSjoerg 154*4d6fc14bSjoergdef produce_top_level_headers(post_include=None, exclusions=None): 155*4d6fc14bSjoerg return produce_headers([include_path], 0, post_include=post_include, exclusions=exclusions) 156*4d6fc14bSjoerg 157*4d6fc14bSjoerg 158*4d6fc14bSjoergdef produce_experimental_headers(post_include=None, exclusions=None): 159*4d6fc14bSjoerg return produce_headers([include_path, 'experimental'], 1, post_include=post_include, exclusions=exclusions) 160*4d6fc14bSjoerg 161*4d6fc14bSjoerg 162*4d6fc14bSjoergdef produce_extended_headers(post_include=None, exclusions=None): 163*4d6fc14bSjoerg return produce_headers([include_path, 'ext'], 0, post_include=post_include, exclusions=exclusions) 164*4d6fc14bSjoerg 165*4d6fc14bSjoerg 166*4d6fc14bSjoergdef replace_generated_headers(test_path, test_str): 167*4d6fc14bSjoerg with open(test_path, 'r') as f: 168*4d6fc14bSjoerg content = f.read() 169*4d6fc14bSjoerg 170*4d6fc14bSjoerg preambule = begin_pattern + '\n// clang-format off\n\n' + warning_note 171*4d6fc14bSjoerg postambule = '\n// clang-format on\n\n' + end_pattern 172*4d6fc14bSjoerg content = generated_part_pattern.sub( 173*4d6fc14bSjoerg preambule + test_str + postambule, content) 174*4d6fc14bSjoerg 175*4d6fc14bSjoerg with open(test_path, 'w', newline='\n') as f: 176*4d6fc14bSjoerg f.write(content) 177*4d6fc14bSjoerg 178*4d6fc14bSjoerg 179*4d6fc14bSjoergdef produce_test(test_filename, exclusions=None, post_include=None): 180*4d6fc14bSjoerg test_str = headers_template.format( 181*4d6fc14bSjoerg top_level_headers=produce_top_level_headers( 182*4d6fc14bSjoerg post_include=post_include, 183*4d6fc14bSjoerg exclusions=exclusions, 184*4d6fc14bSjoerg ), 185*4d6fc14bSjoerg experimental_headers=produce_experimental_headers( 186*4d6fc14bSjoerg post_include=post_include, 187*4d6fc14bSjoerg ), 188*4d6fc14bSjoerg extended_headers=produce_extended_headers( 189*4d6fc14bSjoerg post_include=post_include, 190*4d6fc14bSjoerg ), 191*4d6fc14bSjoerg ) 192*4d6fc14bSjoerg 193*4d6fc14bSjoerg replace_generated_headers(os.path.join( 194*4d6fc14bSjoerg libcxx_test_path, test_filename), test_str) 195*4d6fc14bSjoerg 196*4d6fc14bSjoerg 197*4d6fc14bSjoergdef main(): 198*4d6fc14bSjoerg produce_test('double_include.sh.cpp') 199*4d6fc14bSjoerg produce_test('min_max_macros.compile.pass.cpp', 200*4d6fc14bSjoerg post_include='TEST_MACROS();') 201*4d6fc14bSjoerg produce_test('no_assert_include.compile.pass.cpp', 202*4d6fc14bSjoerg exclusions=['cassert']) 203*4d6fc14bSjoerg 204*4d6fc14bSjoerg 205*4d6fc14bSjoergif __name__ == '__main__': 206*4d6fc14bSjoerg main() 207