xref: /netbsd-src/external/apache2/llvm/dist/libcxx/utils/generate_header_tests.py (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
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