#!/usr/bin/env python3 import sys from os.path import basename, dirname, join, realpath, isfile from glob import iglob import re INCLUDE_PATTERN = re.compile(r'^\s*#include "([\w.]+)"') GUARD_PATTERN = re.compile(r'^#ifndef wren(_\w+)?_h$') WREN_DIR = dirname(dirname(realpath(__file__))) seen_files = set() out = sys.stdout # Find a file in the different folders of the src dir. def find_file(filename): names = [ join(WREN_DIR, 'src', 'include', filename), join(WREN_DIR, 'src', 'vm', filename), join(WREN_DIR, 'src', 'optional', filename), ] for f in names: if isfile(f): return f raise Exception('File "{0}" not found!'.format(filename)) # Prints a plain text file, adding comment markers. def add_comment_file(filename): with open(filename, 'r') as f: for line in f: out.write('// ') out.write(line) # Prints the given C source file, recursively resolving local #includes. def add_file(filename): bname = basename(filename) # Only include each file at most once. if bname in seen_files: return once = False out.write('// Begin file "{0}"\n'.format(bname)) with open(filename, 'r') as f: for line in f: m = INCLUDE_PATTERN.match(line) if m: add_file(find_file(m.group(1))) else: out.write(line) if GUARD_PATTERN.match(line): once = True out.write('// End file "{0}"\n'.format(bname)) # Only skip header files which use #ifndef guards. # This is necessary because of the X Macro technique. if once: seen_files.add(bname) # Print license on top. add_comment_file(join(WREN_DIR, 'LICENSE')) out.write('\n') # Source files. add_file(join(WREN_DIR, 'src', 'include', 'wren.h')) # Must be included here because of conditional compilation. add_file(join(WREN_DIR, 'src', 'vm', 'wren_debug.h')) for f in iglob(join(WREN_DIR, 'src', 'vm', '*.c')): add_file(f) for f in iglob(join(WREN_DIR, 'src', 'optional', '*.c')): add_file(f)