mirror of https://github.com/python/cpython
125 lines
3.5 KiB
Python
125 lines
3.5 KiB
Python
|
import argparse
|
||
|
import ast
|
||
|
import builtins
|
||
|
import collections
|
||
|
import contextlib
|
||
|
import os.path
|
||
|
import sys
|
||
|
|
||
|
|
||
|
assert os.path.isabs(__file__), __file__
|
||
|
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||
|
INTERNAL = os.path.join(ROOT, 'Include', 'internal')
|
||
|
|
||
|
|
||
|
#######################################
|
||
|
# helpers
|
||
|
|
||
|
def iter_to_marker(lines, marker):
|
||
|
for line in lines:
|
||
|
if line.rstrip() == marker:
|
||
|
break
|
||
|
yield line
|
||
|
|
||
|
|
||
|
class Printer:
|
||
|
|
||
|
def __init__(self, file):
|
||
|
self.level = 0
|
||
|
self.file = file
|
||
|
self.continuation = [False]
|
||
|
|
||
|
@contextlib.contextmanager
|
||
|
def indent(self):
|
||
|
save_level = self.level
|
||
|
try:
|
||
|
self.level += 1
|
||
|
yield
|
||
|
finally:
|
||
|
self.level = save_level
|
||
|
|
||
|
def write(self, arg):
|
||
|
eol = '\n'
|
||
|
if self.continuation[-1]:
|
||
|
eol = f' \\{eol}' if arg else f'\\{eol}'
|
||
|
self.file.writelines((" "*self.level, arg, eol))
|
||
|
|
||
|
@contextlib.contextmanager
|
||
|
def block(self, prefix, suffix="", *, continuation=None):
|
||
|
if continuation is None:
|
||
|
continuation = self.continuation[-1]
|
||
|
self.continuation.append(continuation)
|
||
|
|
||
|
self.write(prefix + " {")
|
||
|
with self.indent():
|
||
|
yield
|
||
|
self.continuation.pop()
|
||
|
self.write("}" + suffix)
|
||
|
|
||
|
|
||
|
#######################################
|
||
|
# the global objects
|
||
|
|
||
|
START = '/* The following is auto-generated by Tools/scripts/generate_global_objects.py. */'
|
||
|
END = '/* End auto-generated code */'
|
||
|
|
||
|
|
||
|
def generate_runtime_init():
|
||
|
# First get some info from the declarations.
|
||
|
nsmallposints = None
|
||
|
nsmallnegints = None
|
||
|
with open(os.path.join(INTERNAL, 'pycore_global_objects.h')) as infile:
|
||
|
for line in infile:
|
||
|
if line.startswith('#define _PY_NSMALLPOSINTS'):
|
||
|
nsmallposints = int(line.split()[-1])
|
||
|
elif line.startswith('#define _PY_NSMALLNEGINTS'):
|
||
|
nsmallnegints = int(line.split()[-1])
|
||
|
break
|
||
|
else:
|
||
|
raise NotImplementedError
|
||
|
assert nsmallposints and nsmallnegints
|
||
|
|
||
|
# Then target the runtime initializer.
|
||
|
filename = os.path.join(INTERNAL, 'pycore_runtime_init.h')
|
||
|
|
||
|
# Read the non-generated part of the file.
|
||
|
with open(filename) as infile:
|
||
|
before = ''.join(iter_to_marker(infile, START))[:-1]
|
||
|
for _ in iter_to_marker(infile, END):
|
||
|
pass
|
||
|
after = infile.read()[:-1]
|
||
|
|
||
|
# Generate the file.
|
||
|
with open(filename, 'w', encoding='utf-8') as outfile:
|
||
|
printer = Printer(outfile)
|
||
|
printer.write(before)
|
||
|
printer.write(START)
|
||
|
with printer.block('#define _Py_global_objects_INIT', continuation=True):
|
||
|
with printer.block('.singletons =', ','):
|
||
|
# Global int objects.
|
||
|
with printer.block('.small_ints =', ','):
|
||
|
for i in range(-nsmallnegints, nsmallposints):
|
||
|
printer.write(f'_PyLong_DIGIT_INIT({i}),')
|
||
|
printer.write('')
|
||
|
# Global bytes objects.
|
||
|
printer.write('.bytes_empty = _PyBytes_SIMPLE_INIT(0, 0),')
|
||
|
with printer.block('.bytes_characters =', ','):
|
||
|
for i in range(256):
|
||
|
printer.write(f'_PyBytes_CHAR_INIT({i}),')
|
||
|
printer.write(END)
|
||
|
printer.write(after)
|
||
|
|
||
|
|
||
|
#######################################
|
||
|
# the script
|
||
|
|
||
|
def main() -> None:
|
||
|
generate_runtime_init()
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
argv = sys.argv[1:]
|
||
|
if argv:
|
||
|
sys.exit(f'ERROR: got unexpected args {argv}')
|
||
|
main()
|