|
| 1 | +import argparse |
| 2 | +import os |
| 3 | +import typing |
| 4 | +import yaml |
| 5 | +from enum import Enum |
| 6 | +from string import Template |
| 7 | +from time import gmtime, strftime |
| 8 | + |
| 9 | +parser = argparse.ArgumentParser() |
| 10 | +parser.add_argument("input", type=str, help="OpCode definition file path") |
| 11 | +parser.add_argument("output", type=str, help="Output file name") |
| 12 | + |
| 13 | +args = parser.parse_args() |
| 14 | + |
| 15 | +class Indent: |
| 16 | + stepSize = 4 |
| 17 | + value = 0 |
| 18 | + |
| 19 | + def __init__(self): |
| 20 | + pass |
| 21 | + |
| 22 | + def increase(self): |
| 23 | + self.value += 1 |
| 24 | + |
| 25 | + def decrease(self): |
| 26 | + self.value -= 1 |
| 27 | + |
| 28 | + def reset(self): |
| 29 | + self.value = 0 |
| 30 | + |
| 31 | + def generateSpaces(self): |
| 32 | + return " " * (self.stepSize * self.value) |
| 33 | + |
| 34 | +class OpCodeCppListGenerator: |
| 35 | + prefix = '' |
| 36 | + indent = Indent() |
| 37 | + |
| 38 | + def formatName(self, name): |
| 39 | + return str.upper(name).replace('.', '_') |
| 40 | + |
| 41 | + def generateKey(self, name): |
| 42 | + return self.prefix + name |
| 43 | + |
| 44 | + def generateValue(self, code): |
| 45 | + return code |
| 46 | + |
| 47 | + def prepareItems(self, items): |
| 48 | + result = [] |
| 49 | + |
| 50 | + for i in items: |
| 51 | + if type(i['name']) == type(list()): |
| 52 | + primaryName = i['name'][0] |
| 53 | + |
| 54 | + for n in i['name']: |
| 55 | + stringToAppend = self.indent.generateSpaces() + self.generateKey(self.formatName(n)) \ |
| 56 | + + " = " + self.generateValue(i['code']) |
| 57 | + |
| 58 | + if (n != primaryName): |
| 59 | + stringToAppend += " /* alias for " + self.formatName(primaryName) + " */" |
| 60 | + |
| 61 | + result.append(stringToAppend) |
| 62 | + else: |
| 63 | + result.append(self.indent.generateSpaces() + self.generateKey(self.formatName(i['name'])) + " = " + self.generateValue(i['code'])) |
| 64 | + |
| 65 | + return result |
| 66 | + |
| 67 | + def generateEnumerationLines(self, items): |
| 68 | + lines = self.prepareItems(items) |
| 69 | + |
| 70 | + # Do not use 'os.linesep' on Windows. It generates extra line break |
| 71 | + return str.join(',\n', lines) |
| 72 | + |
| 73 | +currentTime = strftime("%Y-%m-%d %H:%M:%S %z", gmtime()) |
| 74 | + |
| 75 | +cppHeaderFileTemplate = """\ |
| 76 | +#pragma once |
| 77 | +
|
| 78 | +/** |
| 79 | + * ATTENTION! This file was generated automatically. Do NOT change it directly! |
| 80 | + * All direct changes may be overwritten. |
| 81 | + * |
| 82 | + * Generated at: $generatedAt |
| 83 | + */ |
| 84 | +
|
| 85 | +$content |
| 86 | +""" |
| 87 | + |
| 88 | +cppEnumerationTemplate = """\ |
| 89 | +enum $name { |
| 90 | +$items |
| 91 | +};\ |
| 92 | +""" |
| 93 | + |
| 94 | +outputFileName = args.output |
| 95 | +inputFileName = args.input |
| 96 | + |
| 97 | +if outputFileName == None: |
| 98 | + outputFileName = '/._opcodes.h' |
| 99 | + |
| 100 | +inputFile = open(inputFileName, 'r') |
| 101 | + |
| 102 | +opCodeList = yaml.load(inputFile) |
| 103 | +opCodeList = opCodeList['opcodes'] |
| 104 | + |
| 105 | +opCodesFileGeneratorSettings = { |
| 106 | + "outputFileName": outputFileName, |
| 107 | + "fileTemplate": cppHeaderFileTemplate, |
| 108 | + "name": "_GeneratedOpCodes", |
| 109 | + "prefix": "OPCODE_", |
| 110 | +} |
| 111 | + |
| 112 | +with open(opCodesFileGeneratorSettings["outputFileName"], 'w') as f: |
| 113 | + fileTemplate = Template(opCodesFileGeneratorSettings["fileTemplate"]) |
| 114 | + |
| 115 | + cppEnumerationGenerator = OpCodeCppListGenerator() |
| 116 | + cppEnumerationGenerator.prefix = opCodesFileGeneratorSettings["prefix"] |
| 117 | + |
| 118 | + cppEnumerationGenerator.indent.increase() |
| 119 | + renderedItems = cppEnumerationGenerator.generateEnumerationLines( |
| 120 | + opCodeList) |
| 121 | + cppEnumerationGenerator.indent.reset() |
| 122 | + |
| 123 | + enumerationTemplate = Template(cppEnumerationTemplate) |
| 124 | + |
| 125 | + f.write( |
| 126 | + fileTemplate.substitute( |
| 127 | + generatedAt=currentTime, |
| 128 | + content=enumerationTemplate.substitute( |
| 129 | + name=opCodesFileGeneratorSettings["name"], |
| 130 | + items=renderedItems))) |
| 131 | + |
| 132 | +inputFile.close() |
0 commit comments