summaryrefslogtreecommitdiff
path: root/z80count.py
diff options
context:
space:
mode:
authorAlexis Roda <alexis.roda.villalonga@gmail.com>2019-07-27 10:09:52 +0200
committerAlexis Roda <alexis.roda.villalonga@gmail.com>2019-07-27 10:09:52 +0200
commit5f7d94e32812cb02ecde0a9f4fa965002f551c86 (patch)
treeeeffe933a08e3084db2ff0d407e510cf58596d66 /z80count.py
parent3556d259a249135c326fc518100b00829f8f8815 (diff)
downloadz80count-5f7d94e32812cb02ecde0a9f4fa965002f551c86.tar.gz
z80count-5f7d94e32812cb02ecde0a9f4fa965002f551c86.zip
Make a python package.
Diffstat (limited to 'z80count.py')
-rwxr-xr-xz80count.py158
1 files changed, 0 insertions, 158 deletions
diff --git a/z80count.py b/z80count.py
deleted file mode 100755
index 11f7e42..0000000
--- a/z80count.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2019 by Juan J. Martinez <jjm@usebox.net>
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-
-__version__ = "0.5.0"
-
-import json
-import sys
-import re
-import argparse
-from os import path
-
-OUR_COMMENT = re.compile(r"(\[[0-9.\s/]+\])")
-
-
-def z80count(line, parser, total, total_cond, subt, update, tabstop=2, debug=False):
- out = line.rstrip() + "\n"
- entry = parser.lookup(line)
- if entry:
- cycles = entry["cycles"]
- if "/" in cycles:
- c = cycles.split("/")
- total += int(c[1])
- total_cond += total + int(c[0])
- else:
- total += int(cycles)
- total_cond = 0
-
- line = line.rstrip().rsplit(";", 1)
- comment = "; [%s" % cycles
- if subt:
- if total_cond:
- comment += " .. %d/%d]" % (total_cond, total)
- else:
- comment += " .. %d]" % total
- else:
- comment += "]"
- if debug:
- comment += " case{%s}" % entry["case"]
-
- if len(line) == 1:
- comment = "\t" * tabstop + comment
- out = line[0] + comment
- if len(line) > 1:
- if update:
- m = OUR_COMMENT.search(line[1])
- if m:
- line[1] = line[1].replace(m.group(0), "")
- out += " "
- out += line[1].lstrip()
- out += "\n"
-
- return (out, total, total_cond)
-
-
-def parse_command_line():
- parser = argparse.ArgumentParser(
- description='Z80 Cycle Count', epilog="Copyright (C) 2019 Juan J Martinez <jjm@usebox.net>")
-
- parser.add_argument(
- "--version", action="version", version="%(prog)s " + __version__)
- parser.add_argument('-d', dest='debug', action='store_true',
- help="Enable debug (show the matched case)")
- parser.add_argument('-s', dest='subt', action='store_true',
- help="Include subtotal")
- parser.add_argument('-u', dest='update', action='store_true',
- help="Update existing count if available")
- parser.add_argument('-t', dest='tabstop', type=int,
- help="Number of tabs for new comments", default=2)
- parser.add_argument(
- "infile", nargs="?", type=argparse.FileType('r'), default=sys.stdin,
- help="Input file")
- parser.add_argument(
- "outfile", nargs="?", type=argparse.FileType('w'), default=sys.stdout,
- help="Output file")
-
- return parser.parse_args()
-
-
-class Parser(object):
- """Simple parser based on a table of regexes.
-
- """
-
- # [label:] OPERATOR [OPERANDS] [; comment]
- _LINE_RE = re.compile(r"^([\w]+:)?\s*(?P<operator>\w+)(\s+.*)?$")
-
- def __init__(self):
- self._table = self._load_table()
-
- def lookup(self, line):
- mnemo = self._extract_mnemonic(line)
- if mnemo is None or mnemo not in self._table:
- return None
- for entry in self._table[mnemo]:
- if "cregex" not in entry:
- entry["cregex"] = re.compile(r"^\s*" + entry["regex"] + r"\s*(;.*)?$", re.I)
- if entry["cregex"].search(line):
- return entry
- return None
-
- @classmethod
- def _load_table(cls):
- table_file = path.join(path.dirname(path.realpath(__file__)), "z80table.json")
- with open(table_file, "rt") as fd:
- table = json.load(fd)
-
- table.sort(key=lambda o: o["w"])
- res = {}
- for i in table:
- mnemo = cls._extract_mnemonic(i["case"])
- assert mnemo is not None
- if mnemo not in res:
- res[mnemo] = []
- res[mnemo].append(i)
- return res
-
- @classmethod
- def _extract_mnemonic(cls, line):
- match = cls._LINE_RE.match(line)
- if match:
- return match.group("operator").upper()
- return None
-
-
-def main():
- args = parse_command_line()
- in_f = args.infile
- out_f = args.outfile
- parser = Parser()
- total = total_cond = 0
- for line in in_f:
- output, total, total_cond = z80count(
- line, parser, total, total_cond, args.subt, args.update, args.tabstop, args.debug)
- out_f.write(output)
-
-
-if __name__ == "__main__":
- main()