1#! /usr/bin/env python3
2# This script generates Modules/_sre/sre_constants.h from Lib/re/_constants.py.
3
4
5def update_file(file, content):
6    try:
7        with open(file, 'r') as fobj:
8            if fobj.read() == content:
9                return False
10    except (OSError, ValueError):
11        pass
12    with open(file, 'w') as fobj:
13        fobj.write(content)
14    return True
15
16sre_constants_header = """\
17/*
18 * Secret Labs' Regular Expression Engine
19 *
20 * regular expression matching engine
21 *
22 * Auto-generated by Tools/scripts/generate_sre_constants.py from
23 * Lib/re/_constants.py.
24 *
25 * Copyright (c) 1997-2001 by Secret Labs AB.  All rights reserved.
26 *
27 * See the sre.c file for information on usage and redistribution.
28 */
29
30"""
31
32def main(
33    infile="Lib/re/_constants.py",
34    outfile_constants="Modules/_sre/sre_constants.h",
35    outfile_targets="Modules/_sre/sre_targets.h",
36):
37    ns = {}
38    with open(infile) as fp:
39        code = fp.read()
40    exec(code, ns)
41
42    def dump(d, prefix):
43        items = sorted(d)
44        for item in items:
45            yield "#define %s_%s %d\n" % (prefix, item, item)
46
47    def dump2(d, prefix):
48        items = [(value, name) for name, value in d.items()
49                 if name.startswith(prefix)]
50        for value, name in sorted(items):
51            yield "#define %s %d\n" % (name, value)
52
53    def dump_gotos(d, prefix):
54        for i, item in enumerate(sorted(d)):
55            assert i == item
56            yield f"    &&{prefix}_{item},\n"
57
58    content = [sre_constants_header]
59    content.append("#define SRE_MAGIC %d\n" % ns["MAGIC"])
60    content.extend(dump(ns["OPCODES"], "SRE_OP"))
61    content.extend(dump(ns["ATCODES"], "SRE"))
62    content.extend(dump(ns["CHCODES"], "SRE"))
63    content.extend(dump2(ns, "SRE_FLAG_"))
64    content.extend(dump2(ns, "SRE_INFO_"))
65
66    update_file(outfile_constants, ''.join(content))
67
68    content = [sre_constants_header]
69    content.append(f"static void *sre_targets[{len(ns['OPCODES'])}] = {{\n")
70    content.extend(dump_gotos(ns["OPCODES"], "TARGET_SRE_OP"))
71    content.append("};\n")
72
73    update_file(outfile_targets, ''.join(content))
74
75
76if __name__ == '__main__':
77    import sys
78    main(*sys.argv[1:])
79