Skip to content

Commit

Permalink
bpo-47152: Automatically regenerate sre_constants.h (GH-91439)
Browse files Browse the repository at this point in the history
* Move the code for generating Modules/_sre/sre_constants.h from
  Lib/re/_constants.py into a separate script
  Tools/scripts/generate_sre_constants.py.
* Add target `regen-sre` in the makefile.
* Make target `regen-all` depending on `regen-sre`.
  • Loading branch information
serhiy-storchaka committed Apr 12, 2022
1 parent 943ca5e commit 474fdbe
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 46 deletions.
43 changes: 0 additions & 43 deletions Lib/re/_constants.py
Expand Up @@ -215,46 +215,3 @@ def _makecodes(names):
SRE_INFO_PREFIX = 1 # has prefix
SRE_INFO_LITERAL = 2 # entire pattern is literal (given by prefix)
SRE_INFO_CHARSET = 4 # pattern starts with character from given set

if __name__ == "__main__":
def dump(f, d, prefix):
items = sorted(d)
for item in items:
f.write("#define %s_%s %d\n" % (prefix, item, item))
with open("sre_constants.h", "w") as f:
f.write("""\
/*
* Secret Labs' Regular Expression Engine
*
* regular expression matching engine
*
* NOTE: This file is generated by Lib/re/_constants.py. If you need
* to change anything in here, edit Lib/re/_constants.py and run it.
*
* Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved.
*
* See the sre.c file for information on usage and redistribution.
*/
""")

f.write("#define SRE_MAGIC %d\n" % MAGIC)

dump(f, OPCODES, "SRE_OP")
dump(f, ATCODES, "SRE")
dump(f, CHCODES, "SRE")

f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE)
f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE)
f.write("#define SRE_FLAG_MULTILINE %d\n" % SRE_FLAG_MULTILINE)
f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL)
f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE)
f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE)
f.write("#define SRE_FLAG_DEBUG %d\n" % SRE_FLAG_DEBUG)
f.write("#define SRE_FLAG_ASCII %d\n" % SRE_FLAG_ASCII)

f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX)
f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL)
f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET)

print("done")
9 changes: 8 additions & 1 deletion Makefile.pre.in
Expand Up @@ -1197,7 +1197,7 @@ regen-limited-abi: all
# Regenerate all generated files

regen-all: regen-opcode regen-opcode-targets regen-typeslots \
regen-token regen-ast regen-keyword regen-frozen clinic \
regen-token regen-ast regen-keyword regen-sre regen-frozen clinic \
regen-pegen-metaparser regen-pegen regen-test-frozenmain \
regen-global-objects
@echo
Expand Down Expand Up @@ -1350,6 +1350,13 @@ regen-stdlib-module-names: build_all Programs/_testembed
> $(srcdir)/Python/stdlib_module_names.h.new
$(UPDATE_FILE) $(srcdir)/Python/stdlib_module_names.h $(srcdir)/Python/stdlib_module_names.h.new

regen-sre:
# Regenerate Modules/_sre/sre_constants.h from Lib/re/_constants.py
# using Tools/scripts/generate_sre_constants.py
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/generate_sre_constants.py \
$(srcdir)/Lib/re/_constants.py \
$(srcdir)/Modules/_sre/sre_constants.h

Python/compile.o Python/symtable.o Python/ast_unparse.o Python/ast.o Python/future.o: $(srcdir)/Include/internal/pycore_ast.h

Python/getplatform.o: $(srcdir)/Python/getplatform.c
Expand Down
@@ -0,0 +1 @@
Add script and make target for generating ``sre_constants.h``.
4 changes: 2 additions & 2 deletions Modules/_sre/sre_constants.h
Expand Up @@ -3,8 +3,8 @@
*
* regular expression matching engine
*
* NOTE: This file is generated by Lib/re/_constants.py. If you need
* to change anything in here, edit Lib/re/_constants.py and run it.
* Auto-generated by Tools/scripts/generate_sre_constants.py from
* Lib/re/_constants.py.
*
* Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved.
*
Expand Down
62 changes: 62 additions & 0 deletions Tools/scripts/generate_sre_constants.py
@@ -0,0 +1,62 @@
#! /usr/bin/env python3
# This script generates Modules/_sre/sre_constants.h from Lib/re/_constants.py.


def update_file(file, content):
try:
with open(file, 'r') as fobj:
if fobj.read() == content:
return False
except (OSError, ValueError):
pass
with open(file, 'w') as fobj:
fobj.write(content)
return True

sre_constants_header = """\
/*
* Secret Labs' Regular Expression Engine
*
* regular expression matching engine
*
* Auto-generated by Tools/scripts/generate_sre_constants.py from
* Lib/re/_constants.py.
*
* Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved.
*
* See the sre.c file for information on usage and redistribution.
*/
"""

def main(infile='Lib/re/_constants.py', outfile='Modules/_sre/sre_constants.h'):
ns = {}
with open(infile) as fp:
code = fp.read()
exec(code, ns)

def dump(d, prefix):
items = sorted(d)
for item in items:
yield "#define %s_%s %d\n" % (prefix, item, item)

def dump2(d, prefix):
items = [(value, name) for name, value in d.items()
if name.startswith(prefix)]
for value, name in sorted(items):
yield "#define %s %d\n" % (name, value)

content = [sre_constants_header]
content.append("#define SRE_MAGIC %d\n" % ns["MAGIC"])
content.extend(dump(ns["OPCODES"], "SRE_OP"))
content.extend(dump(ns["ATCODES"], "SRE"))
content.extend(dump(ns["CHCODES"], "SRE"))
content.extend(dump2(ns, "SRE_FLAG_"))
content.extend(dump2(ns, "SRE_INFO_"))

update_file(outfile, ''.join(content))


if __name__ == '__main__':
import sys
main(*sys.argv[1:])

0 comments on commit 474fdbe

Please sign in to comment.