Change the parameter name
[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, sourcesDir, 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     ## Destination source dir
33     srcdir = directory + "/bertos"
34     shutil.rmtree(srcdir, True)
35     shutil.copytree(sourcesDir + "/bertos", srcdir)
36     ## Destination makefile
37     makefile = directory + "/Makefile"
38     if os.path.exists(makefile):
39         os.remove(makefile)
40     shutil.copy(sourcesDir + "/Makefile", makefile)
41     ## Destination project dir
42     prjdir = directory + "/" + os.path.basename(directory)
43     shutil.rmtree(prjdir, True)
44     os.mkdir(prjdir)
45
46 def getSystemPath():
47     path = os.environ["PATH"]
48     if os.name == "nt":
49         path = path.split(";")
50     else:
51         path = path.split(":")
52     return path
53
54 def findToolchains(pathList):
55     toolchains = []
56     for element in pathList:
57         for toolchain in glob.glob(element+ "/" + const.GCC_NAME):
58             if not os.path.islink(toolchain):
59                 toolchains.append(toolchain)
60     return list(set(toolchains))
61
62 def getToolchainInfo(output):
63     info = {}
64     expr = re.compile("Target: .*")
65     target = expr.findall(output)
66     if len(target) == 1:
67         info["target"] = target[0].split("Target: ")[1]
68     expr = re.compile("gcc version [0-9,.]*")
69     version = expr.findall(output)
70     if len(version) == 1:
71         info["version"] = version[0].split("gcc version ")[1]
72     expr = re.compile("gcc version [0-9,.]* \(.*\)")
73     build = expr.findall(output)
74     if len(build) == 1:
75         build = build[0].split("gcc version ")[1]
76         build = build[build.find("(") + 1 : build.find(")")]
77         info["build"] = build
78     expr = re.compile("Configured with: .*")
79     configured = expr.findall(output)
80     if len(configured) == 1:
81         info["configured"] = configured[0].split("Configured with: ")[1]
82     expr = re.compile("Thread model: .*")
83     thread = expr.findall(output)
84     if len(thread) == 1:
85         info["thread"] = thread[0].split("Thread model: ")[1]
86     return info
87
88 def findDefinitions(ftype, path):
89     L = os.walk(path)
90     for element in L:
91         for filename in element[2]:
92             if fnmatch.fnmatch(filename, ftype):
93                 yield (filename, element[0])
94
95 def loadCpuInfos(path):
96     cpuInfos = []
97     for definition in findDefinitions(const.CPU_DEFINITION, path):
98         cpuInfos.append(getInfos(definition))
99     return cpuInfos
100
101 def getInfos(definition):
102     D = {}
103     D.update(const.CPU_DEF)
104     def include(filename, dict = D, directory=definition[1]):
105         execfile(directory + "/" + filename, {}, D)
106     D["include"] = include
107     include(definition[0], D)
108     D["CPU_NAME"] = definition[0].split(".")[0]
109     D["DEFINITION_PATH"] = definition[1] + "/" + definition[0]
110     del D["include"]
111     return D
112
113 def getDefinitionBlocks(text):
114     """
115     Take a text and return a list of tuple (description, name-value).
116     """
117     block = []
118     block_tmp = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/\s*#define\s+((?:[^/]*?/?)+)\s*?(?:/{2,3}[^<].*?)?$", text, re.MULTILINE)
119     for comment, define in block_tmp:
120         block.append((" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip(), define))
121     block += re.findall(r"/{3}\s*([^<].*?)\s*#define\s+((?:[^/]*?/?)+)\s*?(?:/{2,3}[^<].*?)?$", text, re.MULTILINE)
122     block += [(comment, define) for define, comment in re.findall(r"#define\s*(.*?)\s*/{3}<\s*(.+?)\s*?(?:/{2,3}[^<].*?)?$", text, re.MULTILINE)]
123     return block
124
125 def formatParamNameValue(text):
126     """
127     Take the given string and return a tuple with the name of the parameter in the first position
128     and the value in the second.
129     """
130     block = re.findall("\s*([^\s]+)\s*(.+?)\s*$", text, re.MULTILINE)
131     return block[0]
132
133 def getDescriptionInformations(text): 
134     """ 
135     Take the doxygen comment and strip the wizard informations, returning the tuple 
136     (comment, wizard_informations) 
137     """ 
138     index = text.find("$WIZARD") 
139     if index != -1: 
140         exec(text[index + 1:]) 
141         informations = WIZARD 
142         return text[:index].strip(), informations
143     else:
144         return text.strip(), {}
145
146 def loadConfigurationInfos(path):
147     """
148     Return the module configurations found in the given file as a dict with the
149     parameter name as key and a dict containig the fields above as value:
150         "value": the value of the parameter
151         "description": the description of the parameter
152         "informations": a dict containig optional informations:
153             "type": "int" | "boolean" | "enum"
154             "min": the minimum value for integer parameters
155             "max": the maximum value for integer parameters
156             "long": boolean indicating if the num is a long
157             "value_list": the name of the enum for enum parameters
158     """
159     configurationInfos = {}
160     for comment, define in getDefinitionBlocks(open(path, "r").read()):
161         name, value = formatParamNameValue(define)
162         description, informations = getDescriptionInformations(comment)
163         configurationInfos[name] = {}
164         configurationInfos[name]["value"] = value
165         configurationInfos[name]["informations"] = informations
166         configurationInfos[name]["description"] = description
167     return configurationInfos
168
169 def loadModuleInfos(path):
170     """
171     Return the module infos found in the given file as a dict with the module
172     name as key and a dict containig the fields above as value or an empty dict
173     if the given file is not a BeRTOS module:
174         "depends": a list of modules needed by this module
175         "configuration": the cfg_*.h with the module configurations
176         "description": a string containing the brief description of doxygen
177         "enabled": contains False but the wizard will change if the user select
178         the module
179     """
180     moduleInfos = {}
181     string = open(path, "r").read()
182     commentList = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/", string)
183     commentList = [" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip() for comment in commentList]
184     for comment in commentList:
185         index = comment.find("$WIZARD_MODULE")
186         if index != -1:
187             exec(comment[index + 1:])
188             moduleInfos[WIZARD_MODULE["name"]] = {"depends": WIZARD_MODULE["depends"],
189                                                     "configuration": WIZARD_MODULE["configuration"],
190                                                     "description": "",
191                                                     "enabled": False}
192             return moduleInfos
193     return {}
194
195 def loadModuleInfosDict(path):
196     """
197     Return the dict containig all the modules
198     """
199     moduleInfosDict = {}
200     for filename, path in findDefinitions("*.h", path):
201         moduleInfosDict.update(loadModuleInfos(path + "/" + filename))
202     return moduleInfosDict
203
204 def loadDefineLists(path):
205     """
206     Return a dict with the name of the list as key and a list of string as value
207     """
208     string = open(path, "r").read()
209     commentList = re.findall(r"/\*{2}\s*([^*]*\*(?:[^/*][^*]*\*+)*)/", string)
210     commentList = [" ".join(re.findall(r"^\s*\*?\s*(.*?)\s*?(?:/{2}.*?)?$", comment, re.MULTILINE)).strip() for comment in commentList]
211     listDict = {}
212     for comment in commentList:
213         index = comment.find("$WIZARD_LIST")
214         if index != -1:
215             exec(comment[index + 1:])
216             listDict.update(WIZARD_LIST)
217     return listDict
218
219 def loadDefineListsDict(path):
220     """
221     Return the dict containing all the define lists
222     """
223     defineListsDict = {}
224     for filename, path in findDefinitions("*.h", path):
225         defineListsDict.update(loadDefineLists(path + "/" + filename))
226     return defineListsDict
227
228 def sub(string, parameter, value):
229     """
230     Substitute the given value at the given parameter define in the given string
231     """
232     return re.sub(r"(?P<define>#define\s+" + parameter + r"\s+)([^\s]+)", r"\g<define>" + value, string)