import fnmatch
import glob
import re
+import shutil
import const
+import DefineException
def isBertosDir(directory):
return os.path.exists(directory + "/VERSION")
def bertosVersion(directory):
return open(directory + "/VERSION").readline().strip()
-def createBertosProject(directory):
+def createBertosProject(projectInfos):
+ directory = projectInfos.info("PROJECT_PATH")
+ sourcesDir = projectInfos.info("SOURCES_PATH")
if not os.path.isdir(directory):
os.mkdir(directory)
- open(directory + "/project.bertos", "w")
+ f = open(directory + "/project.bertos", "w")
+ f.write(repr(projectInfos))
+ f.close()
+ ## Destination source dir
+ srcdir = directory + "/bertos"
+ shutil.rmtree(srcdir, True)
+ shutil.copytree(sourcesDir + "/bertos", srcdir)
+ ## Destination makefile
+ makefile = directory + "/Makefile"
+ if os.path.exists(makefile):
+ os.remove(makefile)
+ makefile = open("mktemplates/Makefile").read()
+ makefile = makefileGenerator(projectInfos, makefile)
+ open(directory + "/Makefile", "w").write(makefile)
+ ## Destination project dir
+ prjdir = directory + "/" + os.path.basename(directory)
+ shutil.rmtree(prjdir, True)
+ os.mkdir(prjdir)
+ ## Destination configurations files
+ cfgdir = prjdir + "/cfg"
+ shutil.rmtree(cfgdir, True)
+ os.mkdir(cfgdir)
+ for key, value in projectInfos.info("CONFIGURATIONS").items():
+ string = open(sourcesDir + "/" + key, "r").read()
+ for parameter, infos in value.items():
+ value = infos["value"]
+ if "unsigned" in infos["informations"].keys() and infos["informations"]["unsigned"]:
+ value += "U"
+ if "long" in infos["informations"].keys() and infos["informations"]["long"]:
+ value += "L"
+ string = sub(string, parameter, value)
+ f = open(cfgdir + "/" + os.path.basename(key), "w")
+ f.write(string)
+ f.close()
+ ## Destinatio mk file
+ makefile = open("mktemplates/template.mk", "r").read()
+ makefile = mkGenerator(projectInfos, makefile)
+ open(prjdir + "/" + os.path.basename(prjdir) + ".mk", "w").write(makefile)
+
+def mkGenerator(projectInfos, makefile):
+ """
+ Generates the mk file for the current project.
+ """
+ mkData = {}
+ mkData["pname"] = os.path.basename(projectInfos.info("PROJECT_PATH"))
+ mkData["cpuname"] = projectInfos.info("CPU_INFOS")["CPU_NAME"]
+ mkData["cflags"] = " ".join(projectInfos.info("CPU_INFOS")["C_FLAGS"])
+ mkData["ldflags"] = " ".join(projectInfos.info("CPU_INFOS")["LD_FLAGS"])
+ for key in mkData:
+ while makefile.find(key) != -1:
+ makefile = makefile.replace(key, mkData[key])
+ return makefile
+
+def makefileGenerator(projectInfos, makefile):
+ """
+ Generate the Makefile for the current project.
+ """
+ # TODO: write a general function that works for both the mk file and the Makefile
+ while makefile.find("project_name") != -1:
+ makefile = makefile.replace("project_name", os.path.basename(projectInfos.info("PROJECT_PATH")))
+ return makefile
def getSystemPath():
path = os.environ["PATH"]
block += [(comment, define) for define, comment in re.findall(r"#define\s*(.*?)\s*/{3}<\s*(.+?)\s*?(?:/{2,3}[^<].*?)?$", text, re.MULTILINE)]
return block
-def formatModuleNameValue(text):
+def formatParamNameValue(text):
"""
Take the given string and return a tuple with the name of the parameter in the first position
and the value in the second.
Take the doxygen comment and strip the wizard informations, returning the tuple
(comment, wizard_informations)
"""
- informations = {}
index = text.find("$WIZARD")
if index != -1:
exec(text[index + 1:])
- informations.update(WIZARD)
- return text[:index].strip(), informations
+ informations = WIZARD
+ return text[:index].strip(), informations
+ else:
+ return text.strip(), {}
-def loadModuleInfos(path):
+def loadConfigurationInfos(path):
"""
- Return the module configurations found in the given path as a dict with the name as key
- and a dict as value. The value dict has the parameter name as key and has "value" and "description"
- fields.
+ Return the module configurations found in the given file as a dict with the
+ parameter name as key and a dict containig the fields above as value:
+ "value": the value of the parameter
+ "description": the description of the parameter
+ "informations": a dict containig optional informations:
+ "type": "int" | "boolean" | "enum"
+ "min": the minimum value for integer parameters
+ "max": the maximum value for integer parameters
+ "long": boolean indicating if the num is a long
+ "value_list": the name of the enum for enum parameters
"""
- moduleInfos = {}
- for definition in findDefinitions(const.MODULE_CONFIGURATION, path):
- moduleName = definition[0].replace("cfg_", "").replace(".h", "")
- moduleInfos[moduleName] = {}
- for comment, define in getDefinitionBlocks(open(definition[1] + "/" + definition[0], "r").read()):
- name, value = formatModuleNameValue(define)
+ try:
+ configurationInfos = {}
+ for comment, define in getDefinitionBlocks(open(path, "r").read()):
+ name, value = formatParamNameValue(define)
description, informations = getDescriptionInformations(comment)
- moduleInfos[moduleName][name] = {}
- moduleInfos[moduleName][name]["value"] = value
- moduleInfos[moduleName][name]["informations"] = informations
- moduleInfos[moduleName][name]["description"] = description
- return moduleInfos
+ configurationInfos[name] = {}
+ configurationInfos[name]["value"] = value
+ configurationInfos[name]["informations"] = informations
+ configurationInfos[name]["description"] = description
+ return configurationInfos
+ except SyntaxError:
+ raise DefineException.ConfigurationDefineException(path)
+
+def loadModuleInfos(path):
+ """
+ Return the module infos found in the given file as a dict with the module
+ name as key and a dict containig the fields above as value or an empty dict
+ if the given file is not a BeRTOS module:
+ "depends": a list of modules needed by this module
+ "configuration": the cfg_*.h with the module configurations
+ "description": a string containing the brief description of doxygen
+ "enabled": contains False but the wizard will change if the user select
+ the module
+ """
+ try:
+ moduleInfos = {}
+ string = open(path, "r").read()
+ commentList = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/", string)
+ commentList = [" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip() for comment in commentList]
+ for comment in commentList:
+ index = comment.find("$WIZARD_MODULE")
+ if index != -1:
+ exec(comment[index + 1:])
+ moduleInfos[WIZARD_MODULE["name"]] = {"depends": WIZARD_MODULE["depends"],
+ "configuration": WIZARD_MODULE["configuration"],
+ "description": "",
+ "enabled": False}
+ return moduleInfos
+ return {}
+ except SyntaxError:
+ raise DefineException.ModuleDefineException(path)
+
+def loadModuleInfosDict(path):
+ """
+ Return the dict containig all the modules
+ """
+ moduleInfosDict = {}
+ for filename, path in findDefinitions("*.h", path):
+ moduleInfosDict.update(loadModuleInfos(path + "/" + filename))
+ return moduleInfosDict
+
+def loadDefineLists(path):
+ """
+ Return a dict with the name of the list as key and a list of string as value
+ """
+ try:
+ string = open(path, "r").read()
+ commentList = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/", string)
+ commentList = [" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip() for comment in commentList]
+ listDict = {}
+ for comment in commentList:
+ index = comment.find("$WIZARD_LIST")
+ if index != -1:
+ exec(comment[index + 1:])
+ listDict.update(WIZARD_LIST)
+ return listDict
+ except SyntaxError:
+ raise DefineException.EnumDefineException(path)
+
+def loadDefineListsDict(path):
+ """
+ Return the dict containing all the define lists
+ """
+ defineListsDict = {}
+ for filename, path in findDefinitions("*.h", path):
+ defineListsDict.update(loadDefineLists(path + "/" + filename))
+ return defineListsDict
+
+def sub(string, parameter, value):
+ """
+ Substitute the given value at the given parameter define in the given string
+ """
+ return re.sub(r"(?P<define>#define\s+" + parameter + r"\s+)([^\s]+)", r"\g<define>" + value, string)
+
+def isInt(value):
+ """
+ Return True if the value is a simple int.
+ """
+ if "long" not in value["informations"].keys() and "unsigned" not in value["informations"].keys():
+ return True
+ else:
+ return False
+
+def isLong(value):
+ """
+ Return True if the value is a long.
+ """
+ if "long" not in value["informations"].keys() and value["informations"]["long"] and "unsigned" not in value["informations"].key():
+ return True
+ else:
+ return False
+
+def isUnsigned(value):
+ """
+ Return True if the value is an unsigned.
+ """
+ if "unsigned" not in value["informations"].keys() and value["informations"]["unsigned"] and "long" not in value["informations"].key():
+ return True
+ else:
+ return False
+
+def isUnsignedLong(value):
+ """
+ Return True if the value is an unsigned long.
+ """
+ if "unsigned" in value["informations"].keys() and "long" in value["informations"].keys() and value["informations"]["unsigned"] and value["informations"]["long"]:
+ return True
+ else:
+ return False
\ No newline at end of file