#!/bin/env python # # The script generates CSS screens for each module type/version. # # Copyright (c) 2018 Oak Ridge National Laboratory. # All rights reserved. # See file LICENSE that is included with this distribution. # # @author Klemen Vodopivec import argparse import os import re import sys __version__ = "0.1.0" def parse_src_file(path, verbose=False): types = { 'createStatusParam': "status", 'createConfigParam': "config", 'createChanConfigParam': "config", 'createCounterParam': "counters", 'createTempParam': "temp" } re_param = re.compile("(create.*Param)\s*\(\"([^\"]*)\"[^;]*;\s*/?/?([^\(]*)(.*)$") re_plugin = re.compile("void (.*)Plugin::createParams.*") params = {} typ = None with open(path, "r") as infile: for line in infile: match = re_plugin.search(line) if match: typ = match.group(1) continue match = re_param.search(line) if match and match.group(1) in types: typ_ = types[match.group(1)] if typ_ not in params: params[typ_] = [] # Detect mbb[io] options props = match.group(4).strip() dropdown = False if props.startswith("("): for token in props.strip("(").split(","): if "=" in token and token[0].isdigit(): dropdown = True break params[typ_].append({ 'name': match.group(2), 'desc': match.group(3), 'selectable': dropdown, }) return typ, params def xml_escape(text): xml_escape_table = { "&": "&", '"': """, "'": "'", ">": ">", "<": "<", } return "".join(xml_escape_table.get(c,c) for c in text) def generate_config_file(outfile, typ, title, params): outfile.write("\n") outfile.write("\n") outfile.write(" {0}\n".format(title)) outfile.write(" 650\n") row = 0 for param in params: outfile.write(" \n") outfile.write(" Rectangle\n") outfile.write(" 1\n") outfile.write(" {0}\n".format(row*24)) outfile.write(" 665\n") outfile.write(" 25\n") outfile.write(" 1\n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" 5\n") outfile.write(" {0}\n".format(row*24+2)) outfile.write(" 145\n") outfile.write(" 20\n") outfile.write(" {0}\n".format(param['name'])) outfile.write(" {0}\n".format(xml_escape(param['desc']))) outfile.write(" 0") outfile.write(" \n") outfile.write(" \n".format("combo" if param['selectable'] else "textentry")) outfile.write(" $(P){0}\n".format(param['name'])) outfile.write(" 150\n") outfile.write(" {0}\n".format(row*24+2)) outfile.write(" 130\n") outfile.write(" 20\n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" $(P){0}\n".format(param['name'])) outfile.write(" $(P){0}_Saved\n".format(param['name'])) outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" $(P){0}_Saved\n".format(param['name'])) outfile.write(" 380\n") outfile.write(" {0}\n".format(row*24+2)) outfile.write(" 130\n") outfile.write(" 20\n") outfile.write(" \n") # outfile.write(" \n") # outfile.write(" \n") # outfile.write(" Do all\n") # if typ.lower() == "aroc": # outfile.write(" Do position\n") # outfile.write(" \n") # outfile.write(" 515\n") # outfile.write(" {0}\n".format(row*24+2)) # outfile.write(" 90\n") # outfile.write(" 20\n") # outfile.write(" \n") # outfile.write(" \n") # outfile.write(" \n") # outfile.write(" $(actions)\n") # outfile.write(" \n") row += 1 outfile.write(" {0}\n".format(row*24+6)) outfile.write("\n") def generate_table_file(outfile, typ, title, params): outfile.write("\n") outfile.write("\n") outfile.write(" {0}\n".format(title)) outfile.write(" 650\n") row = 0 for param in params: outfile.write(" \n") outfile.write(" Rectangle\n") outfile.write(" 1\n") outfile.write(" {0}\n".format(row*24)) outfile.write(" 282\n") outfile.write(" 25\n") outfile.write(" 1\n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" \n") outfile.write(" 5\n") outfile.write(" {0}\n".format(row*24+2)) outfile.write(" 145\n") outfile.write(" 20\n") outfile.write(" {0}\n".format(param['name'])) outfile.write(" {0}\n".format(xml_escape(param['desc']))) outfile.write(" 0") outfile.write(" \n") outfile.write(" \n") outfile.write(" $(P){0}\n".format(param['name'])) outfile.write(" 150\n") outfile.write(" {0}\n".format(row*24+2)) outfile.write(" 130\n") outfile.write(" 20\n") outfile.write(" \n") row += 1 outfile.write(" {0}\n".format(row*24+6)) outfile.write("\n") def main(): usage = ("%prog -i -o \n") parser = argparse.ArgumentParser(description=usage) parser.add_argument("infile", default=None, help="Input .cpp file") parser.add_argument("outdir", default=None, help="Output directory") parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Verbose mode") args = parser.parse_args() if not args.infile or not args.outdir: parse.print_usage() sys.exit(1) if not os.path.isdir(args.outdir): os.makedirs(args.outdir) typ, params = parse_src_file(args.infile, args.verbose) for filetype,fileparams in params.iteritems(): filename = os.path.basename(args.infile).rsplit(".", 1)[0] filename += "_" + filetype + ".bob" filepath = os.path.join(args.outdir, filename) with open(filepath, "w") as outfile: if filetype is "config": generate_config_file(outfile, typ, "$(D) config", fileparams) else: generate_table_file(outfile, typ, "$(D) " + filetype, fileparams) if __name__ == "__main__": main()