#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2014-2015 Ben Kurtovic # Released under the terms of the MIT License. See LICENSE for details. """ This script generates 'src/assembler/instructions.inc.c' from 'src/assembler/instructions.yml'. It should be run automatically by make when the latter is modified, but can also be run manually. """ from __future__ import print_function import re import time SOURCE = "src/assembler/instructions.yml" DEST = "src/assembler/instructions.inc.c" ENCODING = "utf8" TAB = " " * 4 try: import yaml except ImportError: print("Error: PyYAML is required (https://pypi.python.org/pypi/PyYAML)\n" "If you don't want to rebuild {0}, do:\n`make -t {0}`".format(DEST)) exit(1) re_date = re.compile(r"^(\s*@AUTOGEN_DATE\s*)(.*?)$", re.M) re_inst = re.compile( r"(/\* @AUTOGEN_INST_BLOCK_START \*/\n*)(.*?)" r"(\n*/\* @AUTOGEN_INST_BLOCK_END \*/)", re.S) re_lookup = re.compile( r"(/\* @AUTOGEN_LOOKUP_BLOCK_START \*/\n*)(.*?)" r"(\n*/\* @AUTOGEN_LOOKUP_BLOCK_END \*/)", re.S) def build_inst(name, data): """ Convert data for an individual instruction into a C parse function. """ # TODO return "INST_FUNC({0})\n{{\n}}".format(name) def build_inst_block(data): """ Return the instruction parser block, given instruction data. """ return "\n\n".join(build_inst(k, v) for k, v in sorted(data.items())) def build_lookup_block(data): """ Return the instruction lookup block, given instruction data. """ macro = TAB + "HANDLE({0})" return "\n".join(macro.format(inst) for inst in sorted(data.keys())) def process(template, data): """ Return C code generated from a source template and instruction data. """ inst_block = build_inst_block(data) lookup_block = build_lookup_block(data) date = time.asctime(time.gmtime()) result = re_date.sub(r"\1{0} UTC".format(date), template) result = re_inst.sub(r"\1{0}\3".format(inst_block), result) result = re_lookup.sub(r"\1{0}\3".format(lookup_block), result) return result def main(): """ Main script entry point. """ with open(SOURCE, "r") as fp: text = fp.read().decode(ENCODING) with open(DEST, "r") as fp: template = fp.read().decode(ENCODING) data = yaml.load(text) result = process(template, data) # with open(DEST, "w") as fp: # fp.write(result.encode(ENCODING)) print(result) # TODO: remove me! if __name__ == "__main__": main()