# 20 january 2020 # note: python 3 import abc import fileinput import re import sys def errf(fmt, *args): print(fmt.format(*args), file = sys.stderr) class command(metaclass = abc.ABCMeta): @classmethod @abc.abstractmethod def name(cls): raise NotImplementedError @classmethod @abc.abstractmethod def usageString(cls): raise NotImplementedError # returns the list of filenames to iterate through # returns None if there was an error parsing arguments @abc.abstractmethod def processArgs(self, args): raise NotImplementedError @abc.abstractmethod def run(self, casenames): raise NotImplementedError class listCommand: @classmethod def name(cls): return 'list' @classmethod def usageString(cls): return 'list [source-files...]' def processArgs(self, args): return args def run(self, casenames): for x in casenames: print('Test' + x) command.register(listCommand) headerHeader = '''// Generated by testlist.py; do not edit struct testingprivCase { const char *name; void (*f)(void); }; extern const struct testingprivCase testingprivCases[]; extern const size_t testingprivNumCases;''' headerEntryFmt = 'extern void testingprivImplName(Test{})(void);' class headerCommand: filename = None @classmethod def name(cls): return 'header' @classmethod def usageString(cls): return 'header header-file [source-files...]' def processArgs(self, args): if len(args) < 1: errf('error: output filename missing') return None self.filename = args[0] return args[1:] def run(self, casenames): with open(self.filename, 'wt') as f: print(headerHeader, file = f) for x in casenames: print(headerEntryFmt.format(x), file = f) command.register(headerCommand) sourceHeader = '''// Generated by testlist.py; do not edit #include "test.h" const struct testingprivCase testingprivCases[] = {''' sourceEntryFmt = ' {{ "Test{0}", testingprivImplName(Test{0}) }},' sourceFooter = '''}}; const size_t testingprivNumCases = {};''' class sourceCommand: filename = None @classmethod def name(cls): return 'source' @classmethod def usageString(cls): return 'source source-file [source-files...]' def processArgs(self, args): if len(args) < 1: errf('error: output filename missing') return None self.filename = args[0] return args[1:] def run(self, casenames): with open(self.filename, 'wt') as f: print(sourceHeader, file = f) for x in casenames: print(sourceEntryFmt.format(x), file = f) print(sourceFooter.format(len(casenames)), file = f) command.register(sourceCommand) commands = [ listCommand, headerCommand, sourceCommand, ] def usage(): errf('usage:') errf('{} help', sys.argv[0]) for cmd in commands: errf('{} {}', sys.argv[0], cmd.usageString()) sys.exit(1) def main(): r = re.compile('^(?:Test|TestNoInit)\(([A-Za-z0-9_]+)\)$') if len(sys.argv) < 2: usage() cmdname = sys.argv[1] if cmdname == 'help': usage() cmdtype = None for cmd in commands: if cmd.name() == cmdname: cmdtype = cmd break if cmdtype is None: errf('error: unknown command {!r}', cmdname) usage() cmd = cmdtype() files = cmd.processArgs(sys.argv[2:]) if files is None: usage() casenames = [] for line in fileinput.input(files = files): match = r.match(line) if match is not None: casenames.append(match.group(1)) cmd.run(sorted(casenames)) main()