| 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() |