From d4f53acba851cb4359c995156e114cab593692f4 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sun, 9 Sep 2018 23:56:58 -0400 Subject: [PATCH] merlin mac gen command (WIP) --- merlin-mac-gen.py | 208 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 merlin-mac-gen.py diff --git a/merlin-mac-gen.py b/merlin-mac-gen.py new file mode 100644 index 0000000..13cf6a4 --- /dev/null +++ b/merlin-mac-gen.py @@ -0,0 +1,208 @@ +import sublime +import sublime_plugin +import os +import re +import sys +import time + +class MerlinMacGen(sublime_plugin.TextCommand): + + opcodes = { + 'BRL', 'COP', 'JML', 'JMPL', 'JSL', 'MVN', 'MVP', 'MX', 'PEA', + 'PEI', 'PER', 'REP', 'SEP', 'WDM', 'XCE', 'ADR', 'ADRL', 'ASC', + 'AST', 'BRK', 'CHK', 'CYC', 'DA', 'DAT', 'DB', 'DCI', 'DDB', 'DEND', + 'DFB', 'DL', 'DS', 'DSK', 'DUM', 'DW', 'END', 'ENT', 'EQU', 'ERR', 'EXP', + 'EXT', 'FLS', 'HEX', 'INV', 'KBD', 'LST', 'LSTL', 'LUP', 'OBJ', + 'ORG', 'PAG', 'PAU', 'PMC', 'PUT', 'REL', 'REV', 'SAV', 'SKP', + 'STR', 'TR', 'TTL', 'TYP', 'USE', 'USR', 'VAR', 'XC', 'XREF','=', + '>>>', 'DO', 'ELS', 'EOM', 'FIN', 'IF', 'MAC', '--^', '<<<', + 'CLC', 'CLD', 'CLI', 'CLV', 'DEX', 'DEY', 'INX', 'INY', 'NOP', + 'PHA', 'PHB', 'PHD', 'PHK', 'PHX', 'PHY', 'PLA', 'PLB', 'PLD', + 'PLP', 'PLX', 'PLY', 'RTI', 'RTL', 'RTS', 'SEC', 'SED', 'SEI', + 'STP', 'SWA', 'TAD', 'TAS', 'TAX', 'TAY', 'TCD', 'TCS', 'TDA', + 'TDC', 'TSA', 'TSC', 'TSX', 'TXA', 'TXS', 'TXY', 'TYA', 'TYX', + 'WAI', 'XBA', 'BCC', 'BCS', 'BEQ', 'BGE', 'BLT', 'BMI', 'BNE', + 'BPL', 'BRA', 'BVC', 'BVS', 'ADCL', 'ANDL', 'CMPL', 'EORL', + 'LDAL', 'ORAL', 'SBCL', 'STAL', 'ADC', 'AND', 'ASL', 'BIT', + 'CMP', 'CPX', 'CPY', 'DEC', 'EOR', 'INC', 'JMP', 'JSR', 'LDA', + 'LDX', 'LDY', 'LSR', 'ORA', 'ROL', 'ROR', 'SBC', 'STA', 'STX', + 'STY', 'STZ', 'TRB', 'TSB', 'PHP', 'STRL', 'FLO', 'EXD', 'CAS', + '' + } + re_pmc = re.compile('^[^.,/\\- ]*') + re_dot_s = re.compile('\\.S$', re.IGNORECASE) + re_ws = re.compile('[\t ]+') + re_comment = re.compile('^[\t ]*[;*]') + + def front_matter(self): + buffer = "" + name = self.view.file_name() + if name: + buffer += "* Generated from " + os.path.basename(name) + " on " + time.asctime() + "\n" + else: + buffer += "* Generated on " + time.asctime() + "\n" + buffer += "\n" + return buffer + + def missing_matter(self, missing): + buffer = "" + if len(missing) == 0: + return "" + + buffer = "* Missing Macros\n" + + missing = list(missing) + missing.sort + for macro in missing: + buffer += "* " + macro + "\n" + + buffer += "\n" + return buffer + + + def run(self, edit): + + + missing = set() + known = set() + + view = self.view + all = sublime.Region(0, view.size()) + for r in view.lines(all): + text = view.substr(r).rstrip() + + if text == "" or self.re_comment.match(text): + continue + + line = re.split(self.re_ws, text, maxsplit=2) + if len(line) < 2: + continue + + # _macro args + # PMC _macro,args << . / , - ( Space are separtors. + # >>> _macro + + label = line[0].upper() + opcode = line[1].upper() + + if opcode == "" or opcode[0] == ";": + continue + + if opcode == 'MAC': + # label MAC + if label != "": + known.add(label) + continue + + if opcode in {'PMC', '>>>'} and len(line) > 2: + tmp = line[2].upper() + opcode = self.re_pmc.match(tmp).group(0) + if opcode == "": + continue + + + if opcode in self.opcodes: + continue + if opcode in known: + continue + missing.add(opcode) + + + if len(missing) == 0: + return + + # + buffer = "" + root = "/tmp/supermacs" + for e in os.listdir(root): + + if not self.re_dot_s.search(e): + continue + + path = os.path.join(root, e) + if not os.path.isfile(path): + continue + with open(path,'r') as file: + # print(e + "\n",file=sys.stderr) + buffer += self.one_macro_file(file, known, missing) + + if len(missing) == 0: + break + + buffer = self.front_matter() + self.missing_matter(missing) + buffer + + + view = view.window().new_file() + view.insert(edit, 0, buffer) + # p = 0 + # for m in missing: + # p = p + view.insert(edit, p, str(m) + "\n") + + + def one_macro_file(self, file, known, missing): + inmac = False + buffer = "" + + while True: + text = file.readline() + if not text: + return buffer + + text = text.rstrip() + + if inmac: + buffer += text + "\n" + + if text == "" or self.re_comment.match(text): + continue + + line = re.split(self.re_ws, text, maxsplit=2) + + + if len(line) < 2: + continue + + # if line[0] == "_MMStartUp": + # print(line, file=sys.stderr) + + label = line[0].upper() + opcode = line[1].upper() + + + + if opcode == "" or opcode[0] == ";": + continue + + if opcode == "MAC" and label != "": + # print(label,file=sys.stderr) + # print(label in missing, file=sys.stderr) + + if inmac: + known.add(label) + missing.discard(label) + elif label in missing: + inmac = True + known.add(label) + missing.discard(label) + buffer += text + "\n" + continue + + if opcode in { '<<<', 'EOM' }: + inmac = False + continue + + if not inmac: + continue + + if opcode in {'PMC', '>>>'} and len(line) > 2: + tmp = line[2].upper() + opcode = self.re_pmc.match(tmp).group(0) + if opcode == "": + continue + + if opcode in self.opcodes: + continue + if opcode in known: + continue + missing.add(opcode) +