#!/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()