1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
#! /usr/bin/env -S python3 -u
# Copyright 2024 Eugene Gershnik
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://github.com/gershnik/intrusive_shared_ptr/blob/master/LICENSE
#
# pylint: disable=missing-module-docstring, missing-function-docstring, line-too-long
import sys
import re
from pathlib import Path
from typing import Dict, List
comment_start_re = re.compile(r'\s*/\*.*')
comment_end_re = re.compile(r'.*\*/\s*')
sys_include_re = re.compile(r'\s*#\s*include\s+<([^>]+)>\s*')
lib_include_re = re.compile(r'\s*#\s*include\s+<intrusive_shared_ptr/([^>]+)>\s*')
user_include_re = re.compile(r'\s*#\s*include\s+"([^"]+)"\s*')
SPECIAL_HEADERS = {
'CoreFoundation/CoreFoundation.h':
'''
#if (defined(__APPLE__) && defined(__MACH__))
##INCLUDE##
#endif
'''.lstrip(),
'Unknwn.h':
'''
#if defined(_WIN32)
#define NOMINMAX
##INCLUDE##
#endif
'''.lstrip(),
'Python.h':
'''
#if ISPTR_ENABLE_PYTHON
##INCLUDE##
#endif
'''.lstrip()
}
def process_header(folder: Path, path: Path, sys_includes: List[str], processed_headers:Dict[str, bool], strip_initial_comment: bool):
ret = ""
initial_comment_state = 0
with open(path, "rt", encoding='utf-8') as headerfile:
for line in headerfile:
if strip_initial_comment:
if initial_comment_state == 0:
m = comment_start_re.match(line)
if m:
initial_comment_state = 1
continue
elif initial_comment_state == 1:
m = comment_end_re.match(line)
if m:
initial_comment_state = 2
continue
m = user_include_re.match(line)
if not m:
m = lib_include_re.match(line)
if m:
name = m.group(1)
if not processed_headers.get(name):
new_path = (folder / name).absolute()
ret += process_header(new_path.parent, new_path, sys_includes, processed_headers, strip_initial_comment=True)
processed_headers[name] = True
continue
m = sys_include_re.match(line)
if m:
sys_includes.append(m.group(1))
continue
ret += line
return ret
def combine_headers(folder: Path, template: Path, output: Path):
sys_includes = []
processed_headers = {}
text = process_header(folder, template, sys_includes, processed_headers, strip_initial_comment=False)
sys_includes = list(set(sys_includes))
sys_includes.sort()
sys_includes_text = ""
for sys_include in sys_includes:
inc_line = f"#include <{sys_include}>"
if (repl := SPECIAL_HEADERS.get(sys_include)) is not None:
repl = repl.replace('##INCLUDE##', inc_line)
else:
repl = inc_line
sys_includes_text += ("\n" + repl)
text = text.replace("##SYS_INCLUDES##", sys_includes_text)
output.parent.mkdir(parents=True, exist_ok=True)
with open(output, "wt", encoding='utf-8') as outfile:
print(text, file=outfile)
def main():
mydir = Path(__file__).parent
incdir = mydir.parent / 'inc/intrusive_shared_ptr'
moddir = mydir.parent / 'modules'
combine_headers(incdir, mydir / 'module-template.txt', moddir / 'isptr.cppm')
if __name__ == "__main__":
sys.exit(main())
|