| # takes: fei (either xml or text) and smv, |
| # and produces smv and fault modes files |
| |
| import sys |
| import os.path |
| import logging |
| import _paths |
| import _utils |
| |
| |
| def get_expanded_fei_fname(fei_txt_fname): |
| """Given the fei text file name, provides the file name of the |
| expanded fei """ |
| |
| base_in, _ext = os.path.splitext(fei_txt_fname) |
| return os.path.basename(base_in) + ".xml" |
| |
| |
| def get_extended_smv_fname(smv_fname): |
| full_base, ext = os.path.splitext(smv_fname) |
| base = os.path.basename(full_base) |
| prefix = "extended_" |
| return prefix + base + ext |
| |
| |
| def compile_fei(fei_xml_fname, out_xml_fname, lib_path=None): |
| from feic import feicm |
| |
| feicm.main(fei_xml_fname, out_xml_fname, |
| lib_path or feicm.get_default_fault_lib_path()) |
| |
| |
| def translate_fei_to_xml(fei_txt_fname, outdir, path): |
| """returns the name of generated xml file. Raises RuntimeError |
| is an error occurs while parsing""" |
| from feic.translate import fei_translator |
| |
| out_fei_xml = os.path.join(outdir, get_expanded_fei_fname(fei_txt_fname)) |
| |
| fei_translator.convert_fei_text_to_xml_format( |
| fei_txt_fname, out_fei_xml, path) |
| logging.info("Generated XML fei: " + out_fei_xml) |
| return out_fei_xml |
| |
| |
| def extend_model(smv_fname, fei_fname, outdir, |
| disable_checks=False, disable_cc=False, |
| anonymize=False): |
| import subprocess |
| |
| if not os.path.exists(_paths.BIN_DIR) or not os.path.isdir(_paths.BIN_DIR): |
| raise RuntimeError("Could not find bin directory containing xsap") |
| |
| cmd_pat = """set on_failure_script_quits |
| read_model -i "{smv_in}" |
| flatten_hierarchy |
| fe_load_doc -o "{error_fname}" {disable_checks} -p "{dtd_path}" -i "{xml_fei}" |
| fe_extend_module -m "{fms_fname}" {disable_cc} {anonymize} -o "{smv_out}" |
| quit |
| """ |
| smv_out = os.path.join(outdir, |
| get_extended_smv_fname(smv_fname)) |
| |
| fms_fname = os.path.join(outdir, |
| _utils.get_fms_fname(smv_out)) |
| |
| stdouterr_fname = os.path.join(outdir, "xsap_extend_model.out") |
| if os.path.exists(stdouterr_fname): |
| os.remove(stdouterr_fname) |
| |
| error_fname = os.path.join(outdir, "errors.log") |
| if os.path.exists(error_fname): |
| os.remove(error_fname) |
| |
| # generate command file |
| cmd_fname = os.path.join(outdir, "xsap_extend_model.cmd") |
| with open(cmd_fname, "w") as _cmd_file: |
| _cmd_file.write(cmd_pat.format( |
| smv_in=smv_fname, |
| error_fname=error_fname, |
| disable_checks="-c" if disable_checks else "", |
| dtd_path=_paths.SCHEMA_DIR, |
| xml_fei=fei_fname, |
| fms_fname=fms_fname, |
| disable_cc="-c" if disable_cc else "", |
| anonymize="-A" if anonymize else "", |
| smv_out=smv_out)) |
| logging.info("Generated xsap commands script: " + cmd_fname) |
| |
| logging.info("Invoking xsap to carry out smv extension of " + smv_fname) |
| |
| exe_name = _utils.get_exec_fullname() |
| |
| args = [exe_name, "-source", cmd_fname] |
| |
| with open(stdouterr_fname, "w") as o_file: |
| o_file.write("\n" + "-" * 70) |
| o_file.write("\nInvoking:\n" + " ".join(args)) |
| o_file.write("\n" + "-" * 70) |
| o_file.write("\nContent of %s is:\n" % cmd_fname) |
| o_file.write(open(cmd_fname).read()) |
| res = subprocess.call(args, stdout=o_file, stderr=subprocess.STDOUT) |
| o_file.write("\n" + "-" * 70) |
| o_file.write("\nxsap returned %d\n" % res) |
| o_file.write("-" * 70 + '\n') |
| |
| if res != 0: |
| logging.error("A fatal error occurred") |
| if os.path.exists(error_fname): |
| logging.error("This is content of %s:" % error_fname) |
| with open(error_fname) as _err: |
| for line in _err: |
| if line.strip(): |
| print (" " + line.strip()) |
| |
| if os.path.exists(stdouterr_fname): |
| logging.error("(See also content of file %s)" % stdouterr_fname) |
| |
| sys.exit(1) |
| |
| else: |
| logging.info("Successfully created:") |
| logging.info(" - Extend smv file: '%s'" % smv_out) |
| logging.info(" - Fault modes xml file: '%s'" % fms_fname) |
| |
| return smv_out, fms_fname |
| |
| |
| def handle_options(): |
| """returns (options, input_file): |
| values (as a map) and the name of the input file""" |
| |
| import argparse |
| parser = argparse.ArgumentParser(description="Produces an extend smv file" |
| " out of given nominal smv file and fei") |
| |
| parser.add_argument("smv_file", |
| metavar="SMV-FILE", |
| help="The input nominal smv file name") |
| |
| parser.add_argument("fei_file", |
| metavar="FEI-FILE", |
| #dest="fei_file", |
| help="The input fei file name") |
| |
| parser.add_argument('--xml-fei', '-x', |
| action='store_true', |
| default=False, |
| help='Process XML-format for input fei file') |
| |
| parser.add_argument('--verbose', '-v', |
| action='store_true', |
| default=False, |
| help='Sets verbosity to high level') |
| |
| parser.add_argument('--disable-checks', '-c', |
| action='store_true', |
| default=False, |
| help='Disable semantics checks when ' |
| 'extending model (for debugging)') |
| |
| parser.add_argument( |
| "-p", "--path", |
| default=os.path.join(_paths.DATA_DIR, "fm_library"), |
| metavar="PATH", |
| help="Path to the extension library (default:%(default)s)") |
| |
| parser.add_argument( |
| "-d", "--outdir", |
| default="out", |
| metavar="PATH", |
| help="Output directory, where all generated file should be " |
| "put into (default:%(default)s)") |
| |
| parser.add_argument('--disable-cc', '-C', |
| action='store_true', |
| default=False, |
| help='Disable generation of common cause encoding ' |
| 'when extending model (for debugging)') |
| |
| parser.add_argument('--anonymize', '-A', |
| action='store_true', |
| default=False, |
| help='Anonymize the generated extended model') |
| |
| args = parser.parse_args() |
| |
| for fn in (args.smv_file, args.fei_file): |
| if not os.path.isfile(fn): |
| parser.error("File not found: " + fn) |
| |
| if os.path.exists(args.outdir) and not os.path.isdir(args.outdir): |
| parser.error("Not a directory: " + args.outdir) |
| |
| return args |
| |
| |
| if "__main__" == __name__: |
| _paths.setup_path() |
| args = handle_options() |
| |
| if not os.path.exists(args.outdir): |
| os.makedirs(args.outdir) |
| |
| if args.verbose: |
| logging.getLogger().setLevel(logging.INFO) |
| |
| # convert text format if user specified text format as input |
| try: |
| fei_in = (translate_fei_to_xml(args.fei_file, args.outdir, args.path) |
| if not args.xml_fei |
| else args.fei_file) |
| |
| except RuntimeError as e: |
| logging.error(e) |
| sys.exit(1) |
| |
| base_in, _ext = os.path.splitext(args.fei_file) |
| |
| out_fei_fname = os.path.join( |
| args.outdir, |
| "expanded_" + os.path.basename(base_in) + ".xml") |
| |
| if os.path.isfile(out_fei_fname): |
| logging.info("Removing previously generated expanded XML fei: " + |
| out_fei_fname) |
| os.remove(out_fei_fname) |
| |
| logging.info("Generating expanded XML fei: " + out_fei_fname) |
| compile_fei(fei_in, out_fei_fname, args.path) |
| |
| if not os.path.isfile(out_fei_fname): |
| logging.error("An error occurred while generating expanded XML fei: " + |
| out_fei_fname) |
| else: |
| logging.info("Generated expanded XML fei: " + out_fei_fname) |
| |
| out_smv_fname, out_fms = extend_model( |
| args.smv_file, out_fei_fname, |
| args.outdir, |
| disable_checks=args.disable_checks, |
| disable_cc=args.disable_cc, |
| anonymize=args.anonymize, |
| ) |