fprime/Autocoders/bin/codegen.py
2019-02-09 19:06:23 -08:00

1437 lines
66 KiB
Python

#!/usr/bin/env python
#===============================================================================
# NAME: codegen.py
#
# DESCRIPTION: This script is used to generate components, ports and connectors
# from XML definition files.
#
#===============================================================================
import os
import sys
import time
import glob
import logging
import exceptions
from optparse import OptionParser
from utils import Logger
from utils import ConfigManager
from utils import DictTypeConverter
# Meta-model for Component only generation
from models import CompFactory
from models import PortFactory
from models import TopoFactory
from models import Serialize
from models import ModelParser
# Parsers to read the XML
from parsers import XmlParser
from parsers import XmlComponentParser
from parsers import XmlPortsParser
from parsers import XmlSerializeParser
from parsers import XmlTopologyParser
from lxml import etree
# Comment back in when converters added
# from converters import AmpcsCommandConverter
# from converters import AmpcsTelemetryConverter
# from converters import AmpcsEventConverter
# from converters import InstanceAmpcsCommandConverter
# from converters import InstanceAmpcsTelemetryConverter
# from converters import InstanceAmpcsEventConverter
#@todo: from src.parsers import assembly_parser
#Generators to produce the code
from generators import GenFactory
# Flag to indicate verbose mode.
VERBOSE = False
# Global logger init. below.
PRINT = logging.getLogger('output')
DEBUG = logging.getLogger('debug')
# Used by unit test to disable things.
TEST = False
# After catching exception this is set True
# so a clean up routine deletes *_ac_*.[ch]
# and *_ac_*.xml files within module.
ERROR = False
# Configuration manager object.
CONFIG = ConfigManager.ConfigManager.getInstance()
# Build a default log file name
SYS_TIME = time.gmtime()
# Build Root environmental variable if one exists.
BUILD_ROOT = None
# Deployment name from topology XML only
DEPLOYMENT = None
# Version label for now
class Version:
id = "0.1"
comment = "Initial prototype"
VERSION = Version()
def moveCAndHFiles(path_prefix):
"""
Moves the generated c and h files
to a specific directory.
"""
for f in glob.glob('*.c'):
fp = path_prefix + os.sep + f
os.rename(f,fp)
for f in glob.glob('*.h'):
fp = path_prefix + os.sep + f
os.rename(f,fp)
def cleanUp():
"""
If something failed then clean up files generated.
"""
PRINT.info("ERROR: Cleaning up partially created files.")
for file in glob.glob("*_ac_*.new"):
os.remove(file)
for file in glob.glob("*_token.data"):
os.remove(file)
for file in glob.glob("*_opcode_offset.data"):
os.remove(file)
PRINT.info("Completed.")
sys.exit(-1)
def pinit():
"""
Initialize the option parser and return it.
"""
current_dir = os.getcwd()
usage = "usage: %prog [options] [xml_filename]"
vers = "%prog " + VERSION.id + " " + VERSION.comment
parser = OptionParser(usage, version=vers)
parser.add_option("-b", "--build_root", dest="build_root_flag",
help="Enable search for enviornment variable BUILD_ROOT to establish absolute XML directory path",
action="store_true", default=False)
parser.add_option("-p", "--path", dest="work_path", type="string",
help="Switch to new working directory (def: %s)." % current_dir,
action="store", default=current_dir)
parser.add_option("-v", "--verbose", dest="verbose_flag",
help="Enable verbose mode showing more runtime detail (def: False)",
action="store_true", default=False)
parser.add_option("-t", "--template", dest="impl_flag",
help="Enable generation of *Impl_[hpp,cpp].template implementation template files (def: False)",
action="store_true", default=False)
parser.add_option("-u", "--unit-test", dest="unit_test",
help="Enable generation of unit test component files (def: False)",
action="store_true", default=False)
parser.add_option("-l", "--logger", dest="logger", default="QUIET",
help="Set the logging level <DEBUG | INFO | QUIET> (def: 'QUIET').")
parser.add_option("-L", "--logger-output-file", dest="logger_output",
default=None, help="Set the logger output file. (def: defaultgen.log).")
parser.add_option("-d", "--dependency-file", dest="dependency_file",
default=None, help="Set the output file for build dependencies")
parser.add_option("-g", "--default_dict", dest="default_dict",
help="Generate default GDS dictionary classes", action="store_true", default=False)
parser.add_option("-x", "--xml_topology_dict", dest="xml_topology_dict",
help="Generate XML GDS dictionary file", action="store_true", default=False)
parser.add_option("-T", "--default_topology_dict", dest="default_topology_dict",
help="Generate default GDS topology dictionary classes", action="store_true", default=False)
parser.add_option("-a", "--ampcs_dict", dest="ampcs_dict",
help="Generate AMPCS GDS dictionary classes", action="store_true", default=False)
parser.add_option("-A", "--ampcs_topology_dict", dest="ampcs_topology_dict",
help="Generate AMPCS GDS topology dictionary classes", action="store_true", default=False)
parser.add_option("-o", "--dict_dir", dest="dict_dir",
help="Output directory for dictionary. Needed for -g.", default=None)
parser.add_option("-H", "--html_docs", dest="html_docs",
help="Generate HTML docs for commands, telemetry, events, and parameters", action="store_true", default=False)
parser.add_option("-D", "--html_doc_dir", dest="html_doc_dir",
help="Directory for HTML documentation", default=None)
parser.add_option("-m", "--md_docs", dest="md_docs",
help="Generate MarkDown docs for commands, telemetry, events, and parameters", action="store_true", default=False)
parser.add_option("-M", "--md_doc_dir", dest="md_doc_dir",
help="Directory for MarkDown documentation", default=None)
parser.add_option("-P", "--is_ptr", dest="is_ptr",
help="Generate component ptr's in topology.", action="store_true", default=False)
parser.add_option("-C", "--connect_only", dest="connect_only",
help="Only generate port connections in topology.", action="store_true", default=False)
parser.add_option("-r", "--gen_report", dest="gen_report",
help="Generate reports on component interfaces", action="store_true", default=False)
# author = os.environ['USER']
# parser.add_option("-a", "--author", dest="author", type="string",
# help="Specify the new FSW author (def: %s)." % author,
# action="store", default=author)
# CONFIG = ConfigManager.ConfigManager.getInstance()
# v = CONFIG.get('ipc','FSW_version_id') + '_' + time.strftime("%Y%m%d")
# parser.add_option("-f", "--FSW_version_id", dest="fsw_ver", type="string",
# help="Specify the version ID here (def: %s)." % v,
# action="store", default=v)
return parser
def generate_topology(the_parsed_topology_xml, xml_filename, opt):
DEBUG.debug("Topology xml type description file: %s" % xml_filename)
generator = TopoFactory.TopoFactory.getInstance()
if not(opt.default_topology_dict or opt.ampcs_topology_dict or opt.xml_topology_dict):
generator.set_generate_ID(False)
topology_model = generator.create(the_parsed_topology_xml)
if(opt.is_ptr):
PRINT.info("Topology Components will be initalized as Pointers. ")
topology_model.is_ptr = opt.is_ptr
if(opt.connect_only):
PRINT.info("Only port connections will be generated for Topology.")
topology_model.connect_only = opt.connect_only
generator = GenFactory.GenFactory.getInstance()
if "Ai" in xml_filename:
base = xml_filename.split("Ai")[0]
h_instance_name = base + "_H"
cpp_instance_name = base + "_Cpp"
csv_instance_name = base + "_ID"
cmd_html_instance_name = base + "_Cmd_HTML"
channel_html_instance_name = base + "_Channel_HTML"
event_html_instance_name = base + "_Event_HTML"
else:
PRINT.info("Missing Ai at end of file name...")
raise exceptions.IOError
#Figures out what visitor to use
if opt.default_topology_dict or opt.xml_topology_dict:
generator.configureVisitor(h_instance_name, "InstanceTopologyHVisitor", True, True)
generator.configureVisitor(cpp_instance_name, "InstanceTopologyCppVisitor", True, True)
else:
generator.configureVisitor(h_instance_name, "TopologyHVisitor", True, True)
generator.configureVisitor(cpp_instance_name, "TopologyCppVisitor", True, True)
#Used to generate base ID/base ID window CSV files
if True:
generator.configureVisitor(csv_instance_name , "TopologyIDVisitor" , True , True)
#Used to generate HTML tables of ID's etc.
if opt.default_topology_dict or opt.xml_topology_dict:
generator.configureVisitor(cmd_html_instance_name, "InstanceTopologyCmdHTMLVisitor", True, True)
generator.configureVisitor(channel_html_instance_name, "InstanceTopologyChannelsTMLVisitor", True, True)
generator.configureVisitor(event_html_instance_name, "InstanceTopologyEventsHTMLVisitor", True, True)
#uses the topology model to process the items
if opt.default_topology_dict or opt.ampcs_topology_dict or opt.xml_topology_dict:
#create list of used parsed component xmls
parsed_xml_dict = {}
for comp in the_parsed_topology_xml.get_instances():
if comp.get_type() in topology_model.get_base_id_dict():
parsed_xml_dict[comp.get_type()] = comp.get_comp_xml()
#comp.set_component_object(comp.)
else:
PRINT.info( "Components with type {} aren't in the topology model.".format(comp.get_type()))
'''
If creating AMPCS dictionary, this portion validates channel abbreviations.
A dictionary is created, where each key is an abbreviation which corresponds to a channel name.
While iterating through all the channels, if the dictionary already contains the current channel's abbreviaiton as the key, new abbrevs. are created.
This is done by checking the first n values of the current channel name, then of the current channel name without vowels.
This continues by bumping up the base index of the string search until a unique name is found.
'''
# if opt.ampcs_topology_dict:
# abbrev_dictionary = {} #sets an abbrev to be equal to the associated channel name
# max_char_amount = 3
# for parsed_xml_type in parsed_xml_dict:
# if parsed_xml_dict[parsed_xml_type] == None:
# PRINT.info("XML of type {} is being used, but has not been parsed correctly. Check if file exists or add xml file with the 'import_component_type' tag to the Topology file.".format(parsed_xml_type))
# raise Exception()
# for chan in parsed_xml_dict[parsed_xml_type].get_channels():
# if chan.get_abbrev() == None:
# PRINT.info("Channel {} of component type {} has no abbreviation. Please specify the abbreviation in the component XML file.".format(chan.get_name() , parsed_xml_type))
# elif chan.get_abbrev() not in abbrev_dictionary:
# abbrev_dictionary[chan.get_abbrev()] = (chan.get_name() , parsed_xml_type)
# else:
# PRINT.info("Channel {} of component type {} has the same abbreviation ({}) as channel {} of component type {}. Please make the abbreviations unique.".format(chan.get_name() , parsed_xml_type , chan.get_abbrev() , abbrev_dictionary[chan.get_abbrev()][0] , abbrev_dictionary[chan.get_abbrev()][1]))
# raise Exception()
#
# Hack to set up deployment path for instanced dictionaries (if one exists remove old one)
#
if opt.default_topology_dict:
os.environ["DICT_DIR"] = BUILD_ROOT + os.sep + "Gse/generated" + os.sep + DEPLOYMENT
dict_dir = os.environ["DICT_DIR"]
PRINT.info("Removing old instanced topology dictionaries in: %s", dict_dir)
import shutil
if os.path.exists(dict_dir):
shutil.rmtree(dict_dir)
PRINT.info("Overriding for instanced topology dictionaries the --dict_dir option with xml derived path: %s", dict_dir)
#
xml_list = []
for parsed_xml_type in parsed_xml_dict:
if parsed_xml_dict[parsed_xml_type] == None:
PRINT.info("XML of type {} is being used, but has not been parsed correctly. Check if file exists or add xml file with the 'import_component_type' tag to the Topology file.".format(parsed_xml_type))
raise Exception()
xml_list.append(parsed_xml_dict[parsed_xml_type])
generate_component_instance_dictionary(parsed_xml_dict[parsed_xml_type] , opt , topology_model)
topology_model.set_instance_xml_list(xml_list)
if opt.xml_topology_dict:
topology_dict = etree.Element("dictionary")
topology_dict.attrib["topology"] = the_parsed_topology_xml.get_name()
# create a new XML tree for dictionary
enum_list = etree.Element("enums")
serializable_list = etree.Element("serializables")
command_list = etree.Element("commands")
event_list = etree.Element("events")
telemetry_list = etree.Element("channels")
parameter_list = etree.Element("parameters")
for comp in the_parsed_topology_xml.get_instances():
comp_type = comp.get_type()
comp_name = comp.get_name()
comp_id = int(comp.get_base_id())
PRINT.debug("Processing %s [%s] (%s)"%(comp_name,comp_type,hex(comp_id)))
# check for included serializable XML
if (parsed_xml_dict[comp_type].get_serializable_type_files() != None):
serializable_file_list = parsed_xml_dict[comp_type].get_serializable_type_files()
for serializable_file in serializable_file_list:
serializable_file = BUILD_ROOT + os.sep + serializable_file
serializable_model = XmlSerializeParser.XmlSerializeParser(serializable_file)
if (len(serializable_model.get_includes()) != 0):
raise Exception("%s: Can only include one level of serializable for dictionaries"%serializable_file)
serializable_elem = etree.Element("serializable")
serializable_type = serializable_model.get_namespace() + "::" + serializable_model.get_name()
serializable_elem.attrib["type"] = serializable_type
members_elem = etree.Element("members")
for (member_name, member_type, member_size, member_format_specifier, member_comment) in serializable_model.get_members():
member_elem = etree.Element("member")
member_elem.attrib["name"] = member_name
member_elem.attrib["format_specifier"] = member_format_specifier
if member_comment != None:
member_elem.attrib["description"] = member_comment
if type(member_type) == type(tuple()):
enum_value = 0
type_name = "%s::%s::%s"%(serializable_type,member_name,member_type[0][1])
# Add enum entry
enum_elem = etree.Element("enum")
enum_elem.attrib["type"] = type_name
# Add enum members
for (membername,value,comment) in member_type[1]:
enum_mem = etree.Element("item")
enum_mem.attrib["name"] = membername
# keep track of incrementing enum value
if value != None:
enum_value = int(value)
enum_mem.attrib["value"] = "%d"%enum_value
enum_value = enum_value + 1
if comment != None:
enum_mem.attrib["description"] = comment
enum_elem.append(enum_mem)
enum_list.append(enum_elem)
else:
type_name = member_type
if member_type == "string":
member_elem.attrib["len"] = member.get_size()
member_elem.attrib["type"] = type_name
members_elem.append(member_elem)
serializable_elem.append(members_elem)
serializable_list.append(serializable_elem)
# check for commands
if (parsed_xml_dict[comp_type].get_commands() != None):
for command in parsed_xml_dict[comp_type].get_commands():
PRINT.debug("Processing Command %s"%command.get_mnemonic())
command_elem = etree.Element("command")
command_elem.attrib["component"] = comp_name
command_elem.attrib["mnemonic"] = command.get_mnemonic()
command_elem.attrib["opcode"] = "%s"%(hex(int(command.get_opcodes()[0],base=0) + comp_id))
if ("comment" in command_elem.attrib.keys()):
command_elem.attrib["description"] = command_elem.attrib["comment"]
args_elem = etree.Element("args")
for arg in command.get_args():
arg_elem = etree.Element("arg")
arg_elem.attrib["name"] = arg.get_name()
arg_type = arg.get_type()
if type(arg_type) == type(tuple()):
enum_value = 0
type_name = "%s::%s::%s"%(comp_type,arg.get_name(),arg_type[0][1])
# Add enum entry
enum_elem = etree.Element("enum")
enum_elem.attrib["type"] = type_name
# Add enum members
for (membername,value,comment) in arg_type[1]:
enum_mem = etree.Element("item")
enum_mem.attrib["name"] = membername
# keep track of incrementing enum value
if value != None:
enum_value = int(value)
enum_mem.attrib["value"] = "%d"%enum_value
enum_value = enum_value + 1
if comment != None:
enum_mem.attrib["description"] = comment
enum_elem.append(enum_mem)
enum_list.append(enum_elem)
else:
type_name = arg_type
if arg_type == "string":
arg_elem.attrib["len"] = arg.get_size()
arg_elem.attrib["type"] = type_name
args_elem.append(arg_elem)
command_elem.append(args_elem)
command_list.append(command_elem)
# check for channels
if (parsed_xml_dict[comp_type].get_channels() != None):
for chan in parsed_xml_dict[comp_type].get_channels():
PRINT.debug("Processing Channel %s"%chan.get_name())
channel_elem = etree.Element("channel")
channel_elem.attrib["component"] = comp_name
channel_elem.attrib["name"] = chan.get_name()
channel_elem.attrib["id"] = "%s"%(hex(int(chan.get_ids()[0],base=0) + comp_id))
if chan.get_format_string() != None:
channel_elem.attrib["format_string"] = chan.get_format_string()
if chan.get_comment() != None:
channel_elem.attrib["description"] = chan.get_comment()
channel_elem.attrib["id"] = "%s"%(hex(int(chan.get_ids()[0],base=0) + comp_id))
if ("comment" in channel_elem.attrib.keys()):
channel_elem.attrib["description"] = channel_elem.attrib["comment"]
channel_type = chan.get_type()
if type(channel_type) == type(tuple()):
enum_value = 0
type_name = "%s::%s::%s"%(comp_type,chan.get_name(),channel_type[0][1])
# Add enum entry
enum_elem = etree.Element("enum")
enum_elem.attrib["type"] = type_name
# Add enum members
for (membername,value,comment) in channel_type[1]:
enum_mem = etree.Element("item")
enum_mem.attrib["name"] = membername
# keep track of incrementing enum value
if value != None:
enum_value = int(value)
enum_mem.attrib["value"] = "%d"%enum_value
enum_value = enum_value + 1
if comment != None:
enum_mem.attrib["description"] = comment
enum_elem.append(enum_mem)
enum_list.append(enum_elem)
else:
type_name = channel_type
if channel_type == "string":
channel_elem.attrib["len"] = chan.get_size()
(lr,lo,ly,hy,ho,hr) = chan.get_limits()
if (lr != None):
channel_elem.attrib["low_red"] = lr
if (lo != None):
channel_elem.attrib["low_orange"] = lo
if (ly != None):
channel_elem.attrib["low_yellow"] = ly
if (hy != None):
channel_elem.attrib["high_yellow"] = hy
if (ho != None):
channel_elem.attrib["high_orange"] = ho
if (hr != None):
channel_elem.attrib["hight_red"] = hr
channel_elem.attrib["type"] = type_name
telemetry_list.append(channel_elem)
# check for events
if (parsed_xml_dict[comp_type].get_events() != None):
for event in parsed_xml_dict[comp_type].get_events():
PRINT.debug("Processing Event %s"%event.get_name())
event_elem = etree.Element("event")
event_elem.attrib["component"] = comp_name
event_elem.attrib["name"] = event.get_name()
event_elem.attrib["id"] = "%s"%(hex(int(event.get_ids()[0],base=0) + comp_id))
event_elem.attrib["severity"] = event.get_severity()
format_string = event.get_format_string()
if ("comment" in event_elem.attrib.keys()):
event_elem.attrib["description"] = event_elem.attrib["comment"]
args_elem = etree.Element("args")
arg_num = 0
for arg in event.get_args():
arg_elem = etree.Element("arg")
arg_elem.attrib["name"] = arg.get_name()
arg_type = arg.get_type()
if type(arg_type) == type(tuple()):
enum_value = 0
type_name = "%s::%s::%s"%(comp_type,arg.get_name(),arg_type[0][1])
# Add enum entry
enum_elem = etree.Element("enum")
enum_elem.attrib["type"] = type_name
# Add enum members
for (membername,value,comment) in arg_type[1]:
enum_mem = etree.Element("item")
enum_mem.attrib["name"] = membername
# keep track of incrementing enum value
if value != None:
enum_value = int(value)
enum_mem.attrib["value"] = "%d"%enum_value
enum_value = enum_value + 1
if comment != None:
enum_mem.attrib["description"] = comment
enum_elem.append(enum_mem)
enum_list.append(enum_elem)
# replace enum format string %d with %s for ground system
format_string = DictTypeConverter.DictTypeConverter().format_replace(format_string,arg_num,'d','s')
else:
type_name = arg_type
if arg_type == "string":
arg_elem.attrib["len"] = arg.get_size()
arg_elem.attrib["type"] = type_name
args_elem.append(arg_elem)
arg_num += 1
event_elem.attrib["format_string"] = format_string
event_elem.append(args_elem)
event_list.append(event_elem)
# check for parameters
if (parsed_xml_dict[comp_type].get_parameters() != None):
for parameter in parsed_xml_dict[comp_type].get_parameters():
PRINT.debug("Processing Parameter %s"%chan.get_name())
param_default = None
command_elem_set = etree.Element("command")
command_elem_set.attrib["component"] = comp_name
command_elem_set.attrib["mnemonic"] = parameter.get_name()+ "_PRM_SET"
command_elem_set.attrib["opcode"] = "%s"%(hex(int(parameter.get_set_opcodes()[0],base=0) + comp_id))
if ("comment" in command_elem.attrib.keys()):
command_elem_set.attrib["description"] = command_elem_set.attrib["comment"] + " parameter set"
else:
command_elem_set.attrib["description"] = parameter.get_name() + " parameter set"
args_elem = etree.Element("args")
arg_elem = etree.Element("arg")
arg_elem.attrib["name"] = "val"
arg_type = parameter.get_type()
if type(arg_type) == type(tuple()):
enum_value = 0
type_name = "%s::%s::%s"%(comp_type,arg.get_name(),arg_type[0][1])
# Add enum entry
enum_elem = etree.Element("enum")
enum_elem.attrib["type"] = type_name
# Add enum members
for (membername,value,comment) in arg_type[1]:
enum_mem = etree.Element("item")
enum_mem.attrib["name"] = membername
# keep track of incrementing enum value
if value != None:
enum_value = int(value)
enum_mem.attrib["value"] = "%d"%enum_value
enum_value = enum_value + 1
if comment != None:
enum_mem.attrib["description"] = comment
enum_elem.append(enum_mem)
# assign default to be first enum member
if param_default == None:
param_default = membername
enum_list.append(enum_elem)
else:
type_name = arg_type
if arg_type == "string":
arg_elem.attrib["len"] = arg.get_size()
else:
param_default = "0"
arg_elem.attrib["type"] = type_name
args_elem.append(arg_elem)
command_elem_set.append(args_elem)
command_list.append(command_elem_set)
command_elem_save = etree.Element("command")
command_elem_save.attrib["component"] = comp_name
command_elem_save.attrib["mnemonic"] = parameter.get_name()+ "_PRM_SAVE"
command_elem_save.attrib["opcode"] = "%s"%(hex(int(parameter.get_save_opcodes()[0],base=0) + comp_id))
if ("comment" in command_elem.attrib.keys()):
command_elem_save.attrib["description"] = command_elem_set.attrib["comment"] + " parameter set"
else:
command_elem_save.attrib["description"] = parameter.get_name() + " parameter save"
command_list.append(command_elem_save)
param_elem = etree.Element("parameter")
param_elem.attrib["component"] = comp_name
param_elem.attrib["name"] = parameter.get_name()
param_elem.attrib["id"] = "%s"%(hex(int(parameter.get_ids()[0],base=0) + comp_id))
if parameter.get_default() != None:
param_default = parameter.get_default()
param_elem.attrib["default"] = param_default
parameter_list.append(param_elem)
topology_dict.append(enum_list)
topology_dict.append(serializable_list)
topology_dict.append(command_list)
topology_dict.append(event_list)
topology_dict.append(telemetry_list)
topology_dict.append(parameter_list)
fileName = the_parsed_topology_xml.get_xml_filename().replace("Ai.xml","Dictionary.xml")
PRINT.info ("Generating XML dictionary %s"%fileName)
fd = open(fileName,"w")
fd.write(etree.tostring(topology_dict,pretty_print=True))
initFiles = generator.create("initFiles")
#startSource = generator.create("startSource")
includes1 = generator.create("includes1")
#includes2 = generator.create("includes2")
#namespace = generator.create("namespace")
public = generator.create("public")
finishSource= generator.create("finishSource")
#
# Generate the source code products here.
#
# 1. Open all the files
initFiles(topology_model)
#
# 2. Generate includes and static code here.
includes1(topology_model)
#
# 3. Generate public function to instance components and connect them here.
public(topology_model)
#
# 4. Generate final code here and close all files.
finishSource(topology_model)
return(topology_model)
def generate_component_instance_dictionary(the_parsed_component_xml , opt , topology_model):
global BUILD_ROOT
global DEPLOYMENT
#
parsed_port_xml_list = []
parsed_serializable_xml_list = []
#uses the topology model to process the items
#checks if the topology model exists
if topology_model == None:
PRINT.info("Topology model was not specified. Please also input a topology model when running this command.")
raise exceptions.IOError
port_type_files_list = the_parsed_component_xml.get_port_type_files()
for port_file in port_type_files_list:
if BUILD_ROOT != None:
port_file = BUILD_ROOT + os.sep + port_file
DEBUG.debug("Port xml type description file: %s" % port_file)
if not os.path.exists(port_file):
PRINT.info("ERROR: Port xml specification file %s does not exist!" % port_file)
sys.exit(-1)
xml_parser_obj = XmlPortsParser.XmlPortsParser(port_file)
#print xml_parser_obj.get_args()
parsed_port_xml_list.append(xml_parser_obj)
del(xml_parser_obj)
serializable_type_files_list = the_parsed_component_xml.get_serializable_type_files()
for serializable_file in serializable_type_files_list:
if BUILD_ROOT != None:
serializable_file = BUILD_ROOT + os.sep + serializable_file
DEBUG.debug("Serializable xml type description file: %s" % serializable_file)
if not os.path.exists(serializable_file):
PRINT.info("ERROR: Serializable xml specification file %s does not exist!" % serializable_file)
sys.exit(-1)
xml_parser_obj = XmlSerializeParser.XmlSerializeParser(serializable_file) # Telemetry/Params can only use generated serializable types
# check to make sure that the serializables don't have things that channels and parameters can't have
# can't have external non-xml members
if len(xml_parser_obj.get_include_header_files()):
PRINT.info("ERROR: Component include serializables cannot use user-defined types. file: " % serializable_file)
sys.exit(-1)
#print xml_parser_obj.get_args()
parsed_serializable_xml_list.append(xml_parser_obj)
del(xml_parser_obj)
generator = CompFactory.CompFactory.getInstance()
component_model = generator.create(the_parsed_component_xml, parsed_port_xml_list, parsed_serializable_xml_list)
if opt.default_topology_dict:
default_dict_generator = GenFactory.GenFactory.getInstance()
# iterate through command instances
default_dict_generator.configureVisitor("Commands","InstanceCommandVisitor",True,True)
for command_model in component_model.get_commands():
DEBUG.info("Processing command %s"%command_model.get_mnemonic())
defaultStartCmd = default_dict_generator.create("InstanceDictStart")
defaultCmdHeader = default_dict_generator.create("InstanceDictHeader")
defaultCmdBody = default_dict_generator.create("InstanceDictBody")
defaultStartCmd(command_model , topology_model)
defaultCmdHeader(command_model , topology_model)
defaultCmdBody(command_model , topology_model)
for parameter_model in component_model.get_parameters():
DEBUG.info("Processing parameter %s"%parameter_model.get_name())
defaultStartCmd = default_dict_generator.create("InstanceDictStart")
defaultCmdHeader = default_dict_generator.create("InstanceDictHeader")
defaultCmdBody = default_dict_generator.create("InstanceDictBody")
defaultStartCmd(parameter_model , topology_model)
defaultCmdHeader(parameter_model , topology_model)
defaultCmdBody(parameter_model , topology_model)
default_dict_generator = GenFactory.GenFactory.getInstance()
# iterate through command instances
default_dict_generator.configureVisitor("Events","InstanceEventVisitor",True,True)
for event_model in component_model.get_events():
DEBUG.info("Processing event %s"%event_model.get_name())
defaultStartEvent = default_dict_generator.create("InstanceDictStart")
defaultEventHeader = default_dict_generator.create("InstanceDictHeader")
defaultEventBody = default_dict_generator.create("InstanceDictBody")
defaultStartEvent(event_model , topology_model)
defaultEventHeader(event_model , topology_model)
defaultEventBody(event_model , topology_model)
default_dict_generator = GenFactory.GenFactory.getInstance()
# iterate through command instances
default_dict_generator.configureVisitor("Channels","InstanceChannelVisitor",True,True)
for channel_model in component_model.get_channels():
DEBUG.info("Processing channel %s"%channel_model.get_name())
defaultStartChannel = default_dict_generator.create("InstanceDictStart")
defaultChannelHeader = default_dict_generator.create("InstanceDictHeader")
defaultChannelBody = default_dict_generator.create("InstanceDictBody")
defaultStartChannel(channel_model , topology_model)
defaultChannelHeader(channel_model , topology_model)
defaultChannelBody(channel_model , topology_model)
# if opt.ampcs_topology_dict:
# # Hack to always write AMPCS into correct deployment path...
# # Note note removing it first...
# os.environ["AMPCS_DICT_DIR"] = BUILD_ROOT + os.sep + DEPLOYMENT + os.sep + "dict" + os.sep + "AMPCS"
# dict_dir = os.environ["AMPCS_DICT_DIR"]
# PRINT.info("Overriding for AMPCS dictionaries the --dict_dir option with xml derived path: %s", dict_dir)
# InstanceAmpcsCommandConverter.InstanceAmpcsCommandConverter(component_model , topology_model).writeFile(dict_dir)
# InstanceAmpcsTelemetryConverter.InstanceAmpcsTelemetryConverter(component_model , topology_model).writeFile(dict_dir)
# InstanceAmpcsEventConverter.InstanceAmpcsEventConverter(component_model , topology_model).writeFile(dict_dir)
def generate_component(the_parsed_component_xml, xml_filename, opt , topology_model = None):
"""
Creates a component meta-model, configures visitors and
generates the component files. Nothing is returned.
"""
global BUILD_ROOT
#
parsed_port_xml_list = []
if opt.gen_report:
report_file = open("%sReport.txt"%xml_filename.replace("Ai.xml",""),"w")
num_input_ports = 0
num_output_ports = 0
# Count ports
for port in the_parsed_component_xml.get_ports():
if port.get_direction() == "input":
num_input_ports = num_input_ports + int(port.get_max_number())
if port.get_direction() == "output":
num_output_ports = num_output_ports + int(port.get_max_number())
if len(the_parsed_component_xml.get_ports()):
if (num_input_ports):
report_file.write("Input Ports: %d\n"%num_input_ports)
if (num_output_ports):
report_file.write("Output Ports: %d\n"%num_output_ports)
# Count regular commands
commands = 0
idList = ""
if len(the_parsed_component_xml.get_commands()):
for command in the_parsed_component_xml.get_commands():
commands += len(command.get_opcodes())
for opcode in command.get_opcodes():
idList += opcode + ","
# Count parameter commands
if len(the_parsed_component_xml.get_parameters()):
for parameter in the_parsed_component_xml.get_parameters():
commands += len(parameter.get_set_opcodes())
for opcode in parameter.get_set_opcodes():
idList += opcode + ","
commands += len(parameter.get_save_opcodes())
for opcode in parameter.get_save_opcodes():
idList += opcode + ","
if commands > 0:
report_file.write("Commands: %d\n OpCodes: %s\n"%(commands,idList[:-1]))
if len(the_parsed_component_xml.get_channels()):
idList = ""
channels = 0
for channel in the_parsed_component_xml.get_channels():
channels += len(channel.get_ids())
for id in channel.get_ids():
idList += id + ","
report_file.write("Channels: %d\n ChanIds: %s\n"%(channels,idList[:-1]))
if len(the_parsed_component_xml.get_events()):
idList = ""
events = 0
for event in the_parsed_component_xml.get_events():
events += len(event.get_ids())
for id in event.get_ids():
idList += id + ","
report_file.write("Events: %d\n EventIds: %s\n"%(events,idList[:-1]))
if len(the_parsed_component_xml.get_parameters()):
idList = ""
parameters = 0
for parameter in the_parsed_component_xml.get_parameters():
parameters += len(parameter.get_ids())
for id in parameter.get_ids():
idList += id + ","
report_file.write("Parameters: %d\n ParamIds: %s\n"%(parameters,idList[:-1]))
#
# Configure the meta-model for the component
#
port_type_files_list = the_parsed_component_xml.get_port_type_files()
for port_file in port_type_files_list:
if BUILD_ROOT != None:
port_file = BUILD_ROOT + os.sep + port_file
print(BUILD_ROOT)
DEBUG.debug("Port xml type description file: %s" % port_file)
if not os.path.exists(port_file):
PRINT.info("ERROR: Port xml specification file %s does not exist!" % port_file)
sys.exit(-1)
xml_parser_obj = XmlPortsParser.XmlPortsParser(port_file)
#print xml_parser_obj.get_args()
parsed_port_xml_list.append(xml_parser_obj)
del(xml_parser_obj)
parsed_serializable_xml_list = []
#
# Configure the meta-model for the component
#
serializable_type_files_list = the_parsed_component_xml.get_serializable_type_files()
for serializable_file in serializable_type_files_list:
if BUILD_ROOT != None:
serializable_file = BUILD_ROOT + os.sep + serializable_file
DEBUG.debug("Serializable xml type description file: %s" % serializable_file)
if not os.path.exists(serializable_file):
PRINT.info("ERROR: Serializable xml specification file %s does not exist!" % serializable_file)
sys.exit(-1)
xml_parser_obj = XmlSerializeParser.XmlSerializeParser(serializable_file) # Telemetry/Params can only use generated serializable types
# check to make sure that the serializables don't have things that channels and parameters can't have
# can't have external non-xml members
if len(xml_parser_obj.get_include_header_files()):
PRINT.info("ERROR: Component include serializables cannot use user-defined types. file: " % serializable_file)
sys.exit(-1)
#print xml_parser_obj.get_args()
parsed_serializable_xml_list.append(xml_parser_obj)
del(xml_parser_obj)
#
#for p in the_parsed_component_xml.get_ports():
# print p.get_name(), p.get_type()
#print parsed_port_xml_list
#for p in parsed_port_xml_list:
# print p.get_interface().get_name(), p.get_interface().get_namespace()
# print p.get_args()
# print p.get_include_header_files()
#
generator = CompFactory.CompFactory.getInstance()
component_model = generator.create(the_parsed_component_xml, parsed_port_xml_list, parsed_serializable_xml_list)
#tv = [x for x in component_model.get_events()]
#for event_model in component_model.get_events():
# event_model.set_ids([1,2,3])
# tv.append(event_model)
#
# Configure and create the visitors that will generate the code.
#
generator = GenFactory.GenFactory.getInstance()
#
# Configure each visitor here.
#
if "Ai" in xml_filename:
base = xml_filename.split("Ai")[0]
h_instance_name = base + "_H"
cpp_instance_name = base + "_Cpp"
h_instance_name_tmpl = base + "_Impl_H"
cpp_instance_name_tmpl = base + "_Impl_Cpp"
h_instance_test_name = base + "_Test_H"
cpp_instance_test_name = base + "_Test_Cpp"
h_instance_gtest_name = base + "_GTest_H"
cpp_instance_gtest_name = base + "_GTest_Cpp"
h_instance_test_impl_name = base + "_TestImpl_H"
cpp_instance_test_impl_name = base + "_TestImpl_Cpp"
else:
PRINT.info("Missing Ai at end of file name...")
raise exceptions.IOError
#
if opt.impl_flag:
PRINT.info("Enabled generation of implementation template files...")
generator.configureVisitor(h_instance_name_tmpl, "ImplHVisitor", True, True)
generator.configureVisitor(cpp_instance_name_tmpl, "ImplCppVisitor", True, True)
elif opt.unit_test:
PRINT.info("Enabled generation of unit test component files...")
generator.configureVisitor(h_instance_test_name, "ComponentTestHVisitor", True, True)
generator.configureVisitor(cpp_instance_test_name, "ComponentTestCppVisitor", True, True)
generator.configureVisitor(h_instance_gtest_name, "GTestHVisitor", True, True)
generator.configureVisitor(cpp_instance_gtest_name, "GTestCppVisitor", True, True)
generator.configureVisitor(h_instance_test_impl_name, "TestImplHVisitor", True, True)
generator.configureVisitor(cpp_instance_test_impl_name, "TestImplCppVisitor", True, True)
else:
generator.configureVisitor(h_instance_name, "ComponentHVisitor", True, True)
generator.configureVisitor(cpp_instance_name, "ComponentCppVisitor", True, True)
#for port_file in port_type_files_list:
# if "Ai" in port_file:
# base = port_file.split("Ai")[0]
# h_instance_name = base + "_H"
# cpp_instance_name = base + "_Cpp"
# else:
# PRINT.info("Missing Ai at end of file: %s" % port_file)
# raise exceptions.IOError
# generator.configureVisitor(h_instance_name, "PortCppVisitor", True, True)
# generator.configureVisitor(cpp_instance_name, "PortHVisitor", True, True)
#
# The idea here is that each of these generators is used to create
# a certain portion of each output file.
#
initFiles = generator.create("initFiles")
startSource = generator.create("startSource")
includes1 = generator.create("includes1")
includes2 = generator.create("includes2")
namespace = generator.create("namespace")
public = generator.create("public")
protected = generator.create("protected")
private = generator.create("private")
finishSource= generator.create("finishSource")
#
# Generate the source code products here.
#
# 1. Open all the files
initFiles(component_model)
#
# 2. Produce caltech notice here and other starting stuff.
startSource(component_model)
#
# 3. Generate includes that all files get here.
includes1(component_model)
#
# 4. Generate includes from model that a specific here.
includes2(component_model)
#
# 5. Generate start of namespace here.
namespace(component_model)
#
# 6. Generate public class code here.
public(component_model)
#
# 7. Generate protected class code here.
protected(component_model)
#
# 8. Generate private class code here.
private(component_model)
#
# 9. Generate final code here and close all files.
finishSource(component_model)
#
# if requested, generate ground system dictionary
if opt.default_dict:
if opt.dict_dir == None:
PRINT.info("Dictionary output directory not specified!")
raise exceptions.IOError
os.environ["DICT_DIR"] = opt.dict_dir
default_dict_generator = GenFactory.GenFactory.getInstance()
# iterate through command instances
default_dict_generator.configureVisitor("Commands","CommandVisitor",True,True)
for command_model in component_model.get_commands():
DEBUG.info("Processing command %s"%command_model.get_mnemonic())
defaultStartCmd = default_dict_generator.create("DictStart")
defaultCmdHeader = default_dict_generator.create("DictHeader")
defaultCmdBody = default_dict_generator.create("DictBody")
defaultStartCmd(command_model)
defaultCmdHeader(command_model)
defaultCmdBody(command_model)
for parameter_model in component_model.get_parameters():
DEBUG.info("Processing parameter %s"%parameter_model.get_name())
defaultStartCmd = default_dict_generator.create("DictStart")
defaultCmdHeader = default_dict_generator.create("DictHeader")
defaultCmdBody = default_dict_generator.create("DictBody")
defaultStartCmd(parameter_model)
defaultCmdHeader(parameter_model)
defaultCmdBody(parameter_model)
default_dict_generator = GenFactory.GenFactory.getInstance()
# iterate through command instances
default_dict_generator.configureVisitor("Events","EventVisitor",True,True)
for event_model in component_model.get_events():
DEBUG.info("Processing event %s"%event_model.get_name())
defaultStartEvent = default_dict_generator.create("DictStart")
defaultEventHeader = default_dict_generator.create("DictHeader")
defaultEventBody = default_dict_generator.create("DictBody")
defaultStartEvent(event_model)
defaultEventHeader(event_model)
defaultEventBody(event_model)
default_dict_generator = GenFactory.GenFactory.getInstance()
# iterate through command instances
default_dict_generator.configureVisitor("Channels","ChannelVisitor",True,True)
for channel_model in component_model.get_channels():
DEBUG.info("Processing channel %s"%channel_model.get_name())
defaultStartChannel = default_dict_generator.create("DictStart")
defaultChannelHeader = default_dict_generator.create("DictHeader")
defaultChannelBody = default_dict_generator.create("DictBody")
defaultStartChannel(channel_model)
defaultChannelHeader(channel_model)
defaultChannelBody(channel_model)
if opt.ampcs_dict and not opt.default_topology_dict:
if opt.dict_dir == None:
PRINT.info("Dictionary output directory not specified!")
raise exceptions.IOError
os.environ["AMPCS_DICT_DIR"] = opt.dict_dir
AmpcsCommandConverter.AmpcsCommandConverter(component_model).writeFile(opt.dict_dir)
AmpcsTelemetryConverter.AmpcsTelemetryConverter(component_model).writeFile(opt.dict_dir)
AmpcsEventConverter.AmpcsEventConverter(component_model).writeFile(opt.dict_dir)
if opt.html_docs:
if opt.html_doc_dir == None:
PRINT.info("HTML documentation output directory not specified!")
raise exceptions.IOError
os.environ["HTML_DOC_SUBDIR"] = opt.html_doc_dir
html_doc_generator = GenFactory.GenFactory.getInstance()
html_doc_generator.configureVisitor(base + "_Html", "HtmlDocVisitor", True, True)
htmlStart = html_doc_generator.create("HtmlStart")
htmlDoc = html_doc_generator.create("HtmlDoc")
htmlStart(component_model)
htmlDoc(component_model)
if opt.md_docs:
if opt.md_doc_dir == None:
PRINT.info("MD documentation output directory not specified!")
raise exceptions.IOError
os.environ["MD_DOC_SUBDIR"] = opt.md_doc_dir
md_doc_generator = GenFactory.GenFactory.getInstance()
md_doc_generator.configureVisitor(base + "_Md", "MdDocVisitor", True, True)
mdStart = md_doc_generator.create("MdStart")
mdDoc = md_doc_generator.create("MdDoc")
mdStart(component_model)
mdDoc(component_model)
def generate_port(the_parsed_port_xml, port_file):
"""
Creates a port meta-model, configures visitors and
generates the port/interface type files. Nothing is returned.
"""
#
# Configure the meta-model for the component
#
DEBUG.debug("Port xml type description file: %s" % port_file)
generator = PortFactory.PortFactory.getInstance()
port_model = generator.create(the_parsed_port_xml)
#
# Configure and create the visitors that will generate the code.
#
generator = GenFactory.GenFactory.getInstance()
#
# Configure file names and each visitor here.
#
type = the_parsed_port_xml.get_interface().get_name()
#
# Configure each visitor here.
#
if "Ai" in port_file:
base = port_file.split("Ai")[0]
base = type
h_instance_name = base + "_H"
cpp_instance_name = base + "_Cpp"
else:
PRINT.info("Missing Ai at end of file name...")
raise exceptions.IOError
#
generator.configureVisitor(h_instance_name, "PortCppVisitor", True, True)
generator.configureVisitor(cpp_instance_name, "PortHVisitor", True, True)
#
# The idea here is that each of these generators is used to create
# a certain portion of each output file.
#
initFiles = generator.create("initFiles")
startSource = generator.create("startSource")
includes1 = generator.create("includes1")
includes2 = generator.create("includes2")
namespace = generator.create("namespace")
public = generator.create("public")
protected = generator.create("protected")
private = generator.create("private")
finishSource= generator.create("finishSource")
#
# Generate the source code products here.
#
# 1. Open all the files
initFiles(port_model)
#
# 2. Produce caltech notice here and other starting stuff.
startSource(port_model)
#
# 3. Generate includes that all files get here.
includes1(port_model)
#
# 4. Generate includes from model that a specific here.
includes2(port_model)
#
# 5. Generate start of namespace here.
namespace(port_model)
#
# 6. Generate public class code here.
public(port_model)
#
# 7. Generate protected class code here.
protected(port_model)
#
# 8. Generate private class code here.
private(port_model)
#
# 9. Generate final code here and close all files.
finishSource(port_model)
def generate_serializable(the_serial_xml, opt):
"""
Creates a serializable meta-model class, configures visitors and
generates the serializable class files. Nothing is returned.
"""
#
# Configure the meta-model for the serializable here
#
f = the_serial_xml.get_xml_filename()
DEBUG.debug("Serializable xml type description file: %s" % f)
n = the_serial_xml.get_name()
ns = the_serial_xml.get_namespace()
c = the_serial_xml.get_comment()
i = the_serial_xml.get_includes()
i2 = the_serial_xml.get_include_header_files()
m = the_serial_xml.get_members()
t = the_serial_xml.get_typeid()
model = Serialize.Serialize(f,n,ns,c,i,i2,m,t)
#
# Configure each visitor here.
#
t = f.split(".")[0][-2:]
if ("Ai" in f) & (t == "Ai"):
base = n
h_instance_name = base + "_H"
cpp_instance_name = base + "_Cpp"
else:
PRINT.info("Missing Ai at end of file name...")
raise exceptions.IOError
#
generator = GenFactory.GenFactory.getInstance()
generator.configureVisitor(h_instance_name, "SerialCppVisitor", True, True)
generator.configureVisitor(cpp_instance_name, "SerialHVisitor", True, True)
# only generate if serializable is usable for dictionary. Can't have includes of other types
if opt.default_dict:
if len(i) != 0 or len(i2) != 0:
PRINT.info("Dictionary: Skipping %s because of external includes"%(f))
else:
# borrow source visitor pattern for serializable dictionary
if opt.dict_dir == None:
PRINT.info("Dictionary output directory not specified!")
raise exceptions.IOError
os.environ["DICT_DIR"] = opt.dict_dir
generator.configureVisitor("SerialDict", "SerializableVisitor", True, True)
if opt.default_topology_dict:
if len(i) != 0 or len(i2) != 0:
PRINT.info("Dictionary: Skipping %s because of external includes"%(f))
else:
# borrow source visitor pattern for serializable dictionary
if opt.dict_dir == None:
PRINT.info("Dictionary output directory not specified!")
raise exceptions.IOError
os.environ["DICT_DIR"] = opt.dict_dir
print "\n"
print opt.dict_dir
print "\n"
generator.configureVisitor("SerialDict", "InstanceSerializableVisitor", True, True)
#
# The idea here is that each of these generators is used to create
# a certain portion of each output file.
#
initFiles = generator.create("initFiles")
startSource = generator.create("startSource")
includes1 = generator.create("includes1")
includes2 = generator.create("includes2")
namespace = generator.create("namespace")
public = generator.create("public")
protected = generator.create("protected")
private = generator.create("private")
finishSource= generator.create("finishSource")
#
# Generate the source code products here.
#
# 1. Open all the files
initFiles(model)
#
# 2. Produce caltech notice here and other starting stuff.
startSource(model)
#
# 3. Generate includes that all files get here.
includes1(model)
#
# 4. Generate includes from model that a specific here.
includes2(model)
#
# 5. Generate start of namespace here.
namespace(model)
#
# 6. Generate public class code here.
public(model)
#
# 7. Generate protected class code here.
protected(model)
#
# 8. Generate private class code here.
private(model)
#
# 9. Generate final code here and close all files.
finishSource(model)
def generate_dependency_file(filename, target_file, subst_path, parser, type):
# verify directory exists for dependency file and is directory
if not os.path.isdir(os.path.dirname(filename)):
PRINT.info("ERROR: Dependency file path %s does not exist!",os.path.dirname(full_path))
sys.exit(-1)
# open dependency file
dep_file = open(filename,'w')
# get working directory and normalize path
target_directory = os.getcwd().replace('\\','/')
target_file_local = target_file.replace('\\','/').replace("Ai.xml","Ac.cpp")
subst_path_local = subst_path.replace('\\','/')
# normalize path to target file
full_path = os.path.abspath(target_directory + "/" + target_file_local).replace('\\','/');
# if path to substitute is specified, replace with build root
if subst_path_local != None:
full_path = full_path.replace(subst_path_local,"$(BUILD_ROOT)")
# print("sub: %s\ndep_file: %s\ntdir: %s\ntfile: %s\nfp: %s"%(subst_path_local,filename,target_directory,target_file_local,full_path))
# write target to file
dep_file.write("%s:" % full_path)
# assemble list of files
if type == "interface":
file_list = parser.get_include_header_files() + parser.get_includes_serial_files()
elif type == "component":
file_list = parser.get_port_type_files() + parser.get_header_files() + parser.get_serializable_type_files() + parser.get_imported_dictionary_files()
elif type == "serializable":
file_list = parser.get_include_header_files() + parser.get_includes()
elif type == "assembly" or type == "deployment":
# get list of dependency files from XML/header file list
file_list_tmp = parser.get_comp_type_file_header_dict().keys()
file_list = file_list_tmp
#file_list = list()
#for f in file_list_tmp:
# file_list.append(f.replace("Ai.xml","Ac.hpp"))
else:
PRINT.info("ERROR: Unrecognized dependency type %s!",type)
sys.exit(-1)
# write dependencies
for include in file_list:
# print("include %s\n"%include)
if (subst_path_local != None):
full_path = "$(BUILD_ROOT)/" + include.replace('\\','/')
else:
PRINT.info("ERROR: No build root to attach. Not sure how to generate dependency.")
sys.exit(-1)
dep_file.write("\\\n %s "%full_path)
# carriage return
dep_file.write("\n\n")
# close file
dep_file.close()
def main():
"""
Main program.
"""
global ERROR # prevent local creation of variable
global VERBOSE # prevent local creation of variable
global BUILD_ROOT # environmental variable if set
global GEN_TEST_CODE # indicate if test code should be generated
global DEPLOYMENT # deployment set in topology xml only and used to install new instance dicts
ERROR = False
CONFIG = ConfigManager.ConfigManager.getInstance()
Parser = pinit()
(opt, args) = Parser.parse_args()
VERBOSE = opt.verbose_flag
# Check that the specified working directory exists. Remember, the
# default working directory is the current working directory which
# always exists. We are basically only checking for when the user
# specifies an alternate working directory.
if os.path.exists(opt.work_path) == False:
Parser.error('Specified path does not exist (%s)!' % opt.work_path)
working_dir = opt.work_path
# Get the current working directory so that we can return to it when
# the program completes. We always want to return to the place where
# we started.
starting_directory = os.getcwd()
os.chdir(working_dir)
#print working_dir
#print os.getcwd()
# Configure the logging.
log_level = opt.logger.upper()
log_level_dict = dict()
log_level_dict['QUIET'] = None
log_level_dict['DEBUG'] = logging.DEBUG
log_level_dict['INFO'] = logging.INFO
log_level_dict['WARNING'] = logging.WARN
log_level_dict['ERROR'] = logging.ERROR
log_level_dict['CRITICAL'] = logging.CRITICAL
if log_level_dict[log_level] == None:
stdout_enable = False
else:
stdout_enable = True
log_fd = opt.logger_output
# For now no log file
Logger.connectDebugLogger(log_level_dict[log_level], log_fd, stdout_enable)
Logger.connectOutputLogger(log_fd)
#
# Parse the input Component XML file and create internal meta-model
#
if len(args) == 0:
PRINT.info("Usage: %s [options] xml_filename" % sys.argv[0])
return
else:
xml_filenames = args[0:]
#
# Check for BUILD_ROOT variable for XML port searches
#
if opt.build_root_flag == True:
# Check for BUILD_ROOT env. variable
if ('BUILD_ROOT' in os.environ.keys()) == False:
PRINT.info("ERROR: The -b command option requires that BUILD_ROOT environmental variable be set to root build path...")
sys.exit(-1)
else:
BUILD_ROOT = os.environ['BUILD_ROOT']
ModelParser.BUILD_ROOT = BUILD_ROOT
#PRINT.info("BUILD_ROOT set to %s"%BUILD_ROOT)
for xml_filename in xml_filenames:
xml_filename = os.path.basename(xml_filename)
xml_type = XmlParser.XmlParser(xml_filename)()
if xml_type == "component":
DEBUG.info("Detected Component XML so Generating Component C++ Files...")
the_parsed_component_xml = XmlComponentParser.XmlComponentParser(xml_filename)
generate_component(the_parsed_component_xml, xml_filename, opt)
dependency_parser = the_parsed_component_xml
elif xml_type == "interface":
DEBUG.info("Detected Port type XML so Generating Port type C++ Files...")
the_parsed_port_xml = XmlPortsParser.XmlPortsParser(xml_filename)
generate_port(the_parsed_port_xml, xml_filename)
dependency_parser = the_parsed_port_xml
elif xml_type == "serializable":
DEBUG.info("Detected Serializable XML so Generating Serializable C++ Files...")
the_serial_xml = XmlSerializeParser.XmlSerializeParser(xml_filename)
generate_serializable(the_serial_xml,opt)
dependency_parser = the_serial_xml
elif xml_type == "assembly" or xml_type == "deployment":
DEBUG.info("Detected Topology XML so Generating Topology C++ Files...")
the_parsed_topology_xml = XmlTopologyParser.XmlTopologyParser(xml_filename)
DEPLOYMENT = the_parsed_topology_xml.get_deployment()
print "Found assembly or deployment named: %s\n" % DEPLOYMENT
generate_topology(the_parsed_topology_xml, xml_filename, opt)
dependency_parser = the_parsed_topology_xml
else:
PRINT.info("Invalid XML found...this format not supported")
ERROR=True
if opt.dependency_file != None:
if opt.build_root_flag:
generate_dependency_file(opt.dependency_file, xml_filename, BUILD_ROOT, dependency_parser,xml_type)
# Always return to directory where we started.
os.chdir(starting_directory)
if ERROR == True:
sys.exit(-1)
else:
sys.exit(0)
if __name__ == '__main__':
main()