1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 AbstractSyntaxTree classes for the Bitbake language
7 # Copyright (C) 2003, 2004 Chris Larson
8 # Copyright (C) 2003, 2004 Phil Blundell
9 # Copyright (C) 2009 Holger Hans Peter Freyther
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License version 2 as
13 # published by the Free Software Foundation.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License along
21 # with this program; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 __word__ = re.compile(r"\S+")
27 __parsed_methods__ = bb.methodpool.get_parsed_dict()
33 def append(self, statement):
34 self.statements.append(statement)
38 Apply each statement on the data... in order
40 map(lambda x: x.eval(data), self.statements)
43 def __init__(self, what_file, fn, lineno):
44 self.what_file = what_file
46 self.from_lineno = lineno
50 Include the file and evaluate the statements
52 s = bb.data.expand(self.what_file, data)
53 bb.msg.debug(3, bb.msg.domain.Parsing, "CONF %s:%d: including %s" % (self.from_fn, self.from_lineno, s))
55 # TODO: Cache those includes...
56 statements = StatementGroup()
57 bb.parse.ConfHandler.include(statements, self.from_fn, s, data, False)
61 def __init__(self, var):
65 bb.data.setVarFlag(self.var, "export", 1, data)
69 Various data related updates. For the sake of sanity
70 we have one class doing all this. This means that all
71 this need to be re-evaluated... we might be able to do
72 that faster with multiple classes.
74 def __init__(self, groupd):
80 if "exp" in groupd and groupd["exp"] != None:
81 bb.data.setVarFlag(key, "export", 1, data)
82 if "ques" in groupd and groupd["ques"] != None:
83 val = getFunc(groupd, key, data)
86 elif "colon" in groupd and groupd["colon"] != None:
88 bb.data.update_data(e)
89 val = bb.data.expand(groupd["value"], e)
90 elif "append" in groupd and groupd["append"] != None:
91 val = "%s %s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
92 elif "prepend" in groupd and groupd["prepend"] != None:
93 val = "%s %s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
94 elif "postdot" in groupd and groupd["postdot"] != None:
95 val = "%s%s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
96 elif "predot" in groupd and groupd["predot"] != None:
97 val = "%s%s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
100 if 'flag' in groupd and groupd['flag'] != None:
101 bb.msg.debug(3, bb.msg.domain.Parsing, "setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
102 bb.data.setVarFlag(key, groupd['flag'], val, data)
104 bb.data.setVar(key, val, data)
108 def handleInclude(statements, m, fn, lineno, data, force):
110 statements.append(IncludeNode(m.group(1), fn, lineno))
112 s = bb.data.expand(m.group(1), data)
113 bb.msg.debug(3, bb.msg.domain.Parsing, "CONF %s:%d: including %s" % (fn, lineno, s))
115 bb.parse.ConfHandler.include(statements, fn, s, data, "include required")
117 bb.parse.ConfHandler.include(statements, fn, s, data, False)
119 def handleExport(statements, m, data):
121 statements.append(ExportNode(m.group(1)))
123 bb.data.setVarFlag(m.group(1), "export", 1, data)
125 def handleData(statements, groupd, data):
127 statements.append(DataNode(groupd))
130 if "exp" in groupd and groupd["exp"] != None:
131 bb.data.setVarFlag(key, "export", 1, data)
132 if "ques" in groupd and groupd["ques"] != None:
133 val = getFunc(groupd, key, data)
135 val = groupd["value"]
136 elif "colon" in groupd and groupd["colon"] != None:
137 e = data.createCopy()
138 bb.data.update_data(e)
139 val = bb.data.expand(groupd["value"], e)
140 elif "append" in groupd and groupd["append"] != None:
141 val = "%s %s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
142 elif "prepend" in groupd and groupd["prepend"] != None:
143 val = "%s %s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
144 elif "postdot" in groupd and groupd["postdot"] != None:
145 val = "%s%s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
146 elif "predot" in groupd and groupd["predot"] != None:
147 val = "%s%s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
149 val = groupd["value"]
150 if 'flag' in groupd and groupd['flag'] != None:
151 bb.msg.debug(3, bb.msg.domain.Parsing, "setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
152 bb.data.setVarFlag(key, groupd['flag'], val, data)
154 bb.data.setVar(key, val, data)
156 def getFunc(groupd, key, data):
157 if 'flag' in groupd and groupd['flag'] != None:
158 return bb.data.getVarFlag(key, groupd['flag'], data)
160 return bb.data.getVar(key, data)
162 def handleMethod(statements, func_name, lineno, fn, body, d):
163 if func_name == "__anonymous":
164 funcname = ("__anon_%s_%s" % (lineno, fn.translate(string.maketrans('/.+-', '____'))))
165 if not funcname in bb.methodpool._parsed_fns:
166 text = "def %s(d):\n" % (funcname) + '\n'.join(body)
167 bb.methodpool.insert_method(funcname, text, fn)
168 anonfuncs = bb.data.getVar('__BBANONFUNCS', d) or []
169 anonfuncs.append(funcname)
170 bb.data.setVar('__BBANONFUNCS', anonfuncs, d)
172 bb.data.setVarFlag(func_name, "func", 1, d)
173 bb.data.setVar(func_name, '\n'.join(body), d)
175 def handlePythonMethod(statements, root, body, fn):
176 # Note we will add root to parsedmethods after having parse
177 # 'this' file. This means we will not parse methods from
179 if not root in __parsed_methods__:
180 text = '\n'.join(body)
181 bb.methodpool.insert_method(root, text, fn)
183 def handleMethodFlags(statements, key, m, d):
184 if bb.data.getVar(key, d):
185 # Clean up old version of this piece of metadata, as its
186 # flags could cause problems
187 bb.data.setVarFlag(key, 'python', None, d)
188 bb.data.setVarFlag(key, 'fakeroot', None, d)
189 if m.group("py") is not None:
190 bb.data.setVarFlag(key, "python", "1", d)
192 bb.data.delVarFlag(key, "python", d)
193 if m.group("fr") is not None:
194 bb.data.setVarFlag(key, "fakeroot", "1", d)
196 bb.data.delVarFlag(key, "fakeroot", d)
198 def handleExportFuncs(statements, m, classes, d):
200 n = __word__.findall(fns)
204 allvars.append(classes[-1] + "_" + f)
206 vars = [[ allvars[0], allvars[1] ]]
207 if len(classes) > 1 and classes[-2] is not None:
208 allvars.append(classes[-2] + "_" + f)
210 vars.append([allvars[2], allvars[1]])
211 vars.append([allvars[0], allvars[2]])
213 for (var, calledvar) in vars:
214 if bb.data.getVar(var, d) and not bb.data.getVarFlag(var, 'export_func', d):
217 if bb.data.getVar(var, d):
218 bb.data.setVarFlag(var, 'python', None, d)
219 bb.data.setVarFlag(var, 'func', None, d)
221 for flag in [ "func", "python" ]:
222 if bb.data.getVarFlag(calledvar, flag, d):
223 bb.data.setVarFlag(var, flag, bb.data.getVarFlag(calledvar, flag, d), d)
224 for flag in [ "dirs" ]:
225 if bb.data.getVarFlag(var, flag, d):
226 bb.data.setVarFlag(calledvar, flag, bb.data.getVarFlag(var, flag, d), d)
228 if bb.data.getVarFlag(calledvar, "python", d):
229 bb.data.setVar(var, "\tbb.build.exec_func('" + calledvar + "', d)\n", d)
231 bb.data.setVar(var, "\t" + calledvar + "\n", d)
232 bb.data.setVarFlag(var, 'export_func', '1', d)
234 def handleAddTask(statements, m, d):
235 func = m.group("func")
236 before = m.group("before")
237 after = m.group("after")
240 if func[:3] != "do_":
243 bb.data.setVarFlag(var, "task", 1, d)
245 bbtasks = bb.data.getVar('__BBTASKS', d) or []
246 if not var in bbtasks:
248 bb.data.setVar('__BBTASKS', bbtasks, d)
250 existing = bb.data.getVarFlag(var, "deps", d) or []
251 if after is not None:
252 # set up deps for function
253 for entry in after.split():
254 if entry not in existing:
255 existing.append(entry)
256 bb.data.setVarFlag(var, "deps", existing, d)
257 if before is not None:
258 # set up things that depend on this func
259 for entry in before.split():
260 existing = bb.data.getVarFlag(entry, "deps", d) or []
261 if var not in existing:
262 bb.data.setVarFlag(entry, "deps", [var] + existing, d)
264 def handleBBHandlers(statements, m, d):
266 hs = __word__.findall(fns)
267 bbhands = bb.data.getVar('__BBHANDLERS', d) or []
270 bb.data.setVarFlag(h, "handler", 1, d)
271 bb.data.setVar('__BBHANDLERS', bbhands, d)
273 def handleInherit(statements, m, d):
275 n = __word__.findall(files)
276 bb.parse.BBHandler.inherit(statements, n, d)
279 bb.data.expandKeys(d)
280 bb.data.update_data(d)
281 anonqueue = bb.data.getVar("__anonqueue", d, 1) or []
282 body = [x['content'] for x in anonqueue]
283 flag = { 'python' : 1, 'func' : 1 }
284 bb.data.setVar("__anonfunc", "\n".join(body), d)
285 bb.data.setVarFlags("__anonfunc", flag, d)
288 t = bb.data.getVar('T', d)
289 bb.data.setVar('T', '${TMPDIR}/anonfunc/', d)
290 anonfuncs = bb.data.getVar('__BBANONFUNCS', d) or []
293 code = code + " %s(d)\n" % f
294 bb.data.setVar("__anonfunc", code, d)
295 build.exec_func("__anonfunc", d)
296 bb.data.delVar('T', d)
298 bb.data.setVar('T', t, d)
300 bb.msg.debug(1, bb.msg.domain.Parsing, "Exception when executing anonymous function: %s" % e)
302 bb.data.delVar("__anonqueue", d)
303 bb.data.delVar("__anonfunc", d)
304 bb.data.update_data(d)
307 for var in bb.data.getVar('__BBHANDLERS', d) or []:
308 # try to add the handler
309 handler = bb.data.getVar(var,d)
310 bb.event.register(var, handler)
312 tasklist = bb.data.getVar('__BBTASKS', d) or []
313 bb.build.add_tasks(tasklist, d)
315 bb.event.fire(bb.event.RecipeParsed(fn), d)