Create a bertos project folder and copy the bertos source tree
[bertos.git] / wizard / bertos_utils.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 #
4 # Copyright 2008 Develer S.r.l. (http://www.develer.com/)
5 # All rights reserved.
6 #
7 # $Id:$
8 #
9 # Author: Lorenzo Berni <duplo@develer.com>
10 #
11
12 import os
13 import fnmatch
14 import glob
15 import re
16 import shutil
17
18 import const
19
20 def isBertosDir(directory):
21    return os.path.exists(directory + "/VERSION")
22
23 def bertosVersion(directory):
24    return open(directory + "/VERSION").readline().strip()
25
26 def createBertosProject(directory, sources_dir, projectInfos):
27     if not os.path.isdir(directory):
28         os.mkdir(directory)
29     f = open(directory + "/project.bertos", "w")
30     f.write(repr(projectInfos))
31     f.close()
32     shutil.rmtree(directory + "/bertos", True)
33     shutil.copytree(sources_dir + "/bertos", directory + "/bertos")
34     shutil.copy(sources_dir + "/Makefile", directory + "/Makefile")
35
36 def getSystemPath():
37     path = os.environ["PATH"]
38     if os.name == "nt":
39         path = path.split(";")
40     else:
41         path = path.split(":")
42     return path
43
44 def findToolchains(pathList):
45     toolchains = []
46     for element in pathList:
47         for toolchain in glob.glob(element+ "/" + const.GCC_NAME):
48             if not os.path.islink(toolchain):
49                 toolchains.append(toolchain)
50     return list(set(toolchains))
51
52 def getToolchainInfo(output):
53     info = {}
54     expr = re.compile("Target: .*")
55     target = expr.findall(output)
56     if len(target) == 1:
57         info["target"] = target[0].split("Target: ")[1]
58     expr = re.compile("gcc version [0-9,.]*")
59     version = expr.findall(output)
60     if len(version) == 1:
61         info["version"] = version[0].split("gcc version ")[1]
62     expr = re.compile("gcc version [0-9,.]* \(.*\)")
63     build = expr.findall(output)
64     if len(build) == 1:
65         build = build[0].split("gcc version ")[1]
66         build = build[build.find("(") + 1 : build.find(")")]
67         info["build"] = build
68     expr = re.compile("Configured with: .*")
69     configured = expr.findall(output)
70     if len(configured) == 1:
71         info["configured"] = configured[0].split("Configured with: ")[1]
72     expr = re.compile("Thread model: .*")
73     thread = expr.findall(output)
74     if len(thread) == 1:
75         info["thread"] = thread[0].split("Thread model: ")[1]
76     return info
77
78 def findDefinitions(ftype, path):
79     L = os.walk(path)
80     for element in L:
81         for filename in element[2]:
82             if fnmatch.fnmatch(filename, ftype):
83                 yield (filename, element[0])
84
85 def loadCpuInfos(path):
86     cpuInfos = []
87     for definition in findDefinitions(const.CPU_DEFINITION, path):
88         cpuInfos.append(getInfos(definition))
89     return cpuInfos
90
91 def getInfos(definition):
92     D = {}
93     D.update(const.CPU_DEF)
94     def include(filename, dict = D, directory=definition[1]):
95         execfile(directory + "/" + filename, {}, D)
96     D["include"] = include
97     include(definition[0], D)
98     D["CPU_NAME"] = definition[0].split(".")[0]
99     D["DEFINITION_PATH"] = definition[1] + "/" + definition[0]
100     del D["include"]
101     return D
102
103 def getDefinitionBlocks(text):
104     """
105     Take a text and return a list of tuple (description, name-value).
106     """
107     block = []
108     block_tmp = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/\s*#define\s+((?:[^/]*?/?)+)\s*?(?:/{2,3}[^<].*?)?$", text, re.MULTILINE)
109     for comment, define in block_tmp:
110         block.append((" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip(), define))
111     block += re.findall(r"/{3}\s*([^<].*?)\s*#define\s+((?:[^/]*?/?)+)\s*?(?:/{2,3}[^<].*?)?$", text, re.MULTILINE)
112     block += [(comment, define) for define, comment in re.findall(r"#define\s*(.*?)\s*/{3}<\s*(.+?)\s*?(?:/{2,3}[^<].*?)?$", text, re.MULTILINE)]
113     return block
114
115 def formatParamNameValue(text):
116     """
117     Take the given string and return a tuple with the name of the parameter in the first position
118     and the value in the second.
119     """
120     block = re.findall("\s*([^\s]+)\s*(.+?)\s*$", text, re.MULTILINE)
121     return block[0]
122
123 def getDescriptionInformations(text): 
124     """ 
125     Take the doxygen comment and strip the wizard informations, returning the tuple 
126     (comment, wizard_informations) 
127     """ 
128     index = text.find("$WIZARD") 
129     if index != -1: 
130         exec(text[index + 1:]) 
131         informations = WIZARD 
132         return text[:index].strip(), informations
133     else:
134         return text.strip(), {}
135
136 def loadConfigurationInfos(path):
137     """
138     Return the module configurations found in the given file as a dict with the
139     parameter name as key and a dict containig the fields above as value:
140         "value": the value of the parameter
141         "description": the description of the parameter
142         "informations": a dict containig optional informations:
143             "type": "int" | "boolean" | "enum"
144             "min": the minimum value for integer parameters
145             "max": the maximum value for integer parameters
146             "long": boolean indicating if the num is a long
147             "value_list": the name of the enum for enum parameters
148     """
149     configurationInfos = {}
150     for comment, define in getDefinitionBlocks(open(path, "r").read()):
151         name, value = formatParamNameValue(define)
152         description, informations = getDescriptionInformations(comment)
153         configurationInfos[name] = {}
154         configurationInfos[name]["value"] = value
155         configurationInfos[name]["informations"] = informations
156         configurationInfos[name]["description"] = description
157     return configurationInfos
158
159 def loadModuleInfos(path):
160     """
161     Return the module infos found in the given file as a dict with the module
162     name as key and a dict containig the fields above as value or an empty dict
163     if the given file is not a BeRTOS module:
164         "depends": a list of modules needed by this module
165         "configuration": the cfg_*.h with the module configurations
166         "description": a string containing the brief description of doxygen
167         "enabled": contains False but the wizard will change if the user select
168         the module
169     """
170     moduleInfos = {}
171     string = open(path, "r").read()
172     commentList = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/", string)
173     commentList = [" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip() for comment in commentList]
174     for comment in commentList:
175         index = comment.find("$WIZARD_MODULE")
176         if index != -1:
177             exec(comment[index + 1:])
178             moduleInfos[WIZARD_MODULE["name"]] = {"depends": WIZARD_MODULE["depends"],
179                                                     "configuration": WIZARD_MODULE["configuration"],
180                                                     "description": "",
181                                                     "enabled": False}
182             return moduleInfos
183     return {}
184
185 def loadModuleInfosDict(path):
186     """
187     Return the dict containig all the modules
188     """
189     moduleInfosDict = {}
190     for filename, path in findDefinitions("*.h", path):
191         moduleInfosDict.update(loadModuleInfos(path + "/" + filename))
192     return moduleInfosDict
193
194 def loadDefineLists(path):
195     """
196     Return a dict with the name of the list as key and a list of string as value
197     """
198     string = open(path, "r").read()
199     commentList = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/", string)
200     commentList = [" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip() for comment in commentList]
201     listDict = {}
202     for comment in commentList:
203         index = comment.find("$WIZARD_LIST")
204         if index != -1:
205             exec(comment[index + 1:])
206             listDict.update(WIZARD_LIST)
207     return listDict
208
209 def loadDefineListsDict(path):
210     """
211     Return the dict containing all the define lists
212     """
213     defineListsDict = {}
214     for filename, path in findDefinitions("*.h", path):
215         defineListsDict.update(loadDefineLists(path + "/" + filename))
216     return defineListsDict