[parser] Cary a Statement Node through the parsing
[bitbake.git] / lib / bb / parse / ast.py
1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3 """
4  AbstractSyntaxTree classes for the Bitbake language
5 """
6
7 # Copyright (C) 2003, 2004 Chris Larson
8 # Copyright (C) 2003, 2004 Phil Blundell
9 # Copyright (C) 2009 Holger Hans Peter Freyther
10 #
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.
14 #
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.
19 #
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.
23
24 import bb, re, string
25
26 __word__ = re.compile(r"\S+")
27 __parsed_methods__ = bb.methodpool.get_parsed_dict()
28
29 class StatementGroup:
30     def __init__(self):
31         self.statements = []
32
33     def eval(self, data):
34         """
35         Apply each statement on the data... in order
36         """
37         map(lambda x: x.eval(data), self.statements)
38
39 def handleInclude(statements, m, fn, lineno, data, force):
40     s = bb.data.expand(m.group(1), data)
41     bb.msg.debug(3, bb.msg.domain.Parsing, "CONF %s:%d: including %s" % (fn, lineno, s))
42     if force:
43         bb.parse.ConfHandler.include(statements, fn, s, data, "include required")
44     else:
45         bb.parse.ConfHandler.include(statements, fn, s, data, False)
46
47 def handleExport(statements, m, data):
48     bb.data.setVarFlag(m.group(1), "export", 1, data)
49
50 def handleData(statements, groupd, data):
51     key = groupd["var"]
52     if "exp" in groupd and groupd["exp"] != None:
53         bb.data.setVarFlag(key, "export", 1, data)
54     if "ques" in groupd and groupd["ques"] != None:
55         val = getFunc(groupd, key, data)
56         if val == None:
57             val = groupd["value"]
58     elif "colon" in groupd and groupd["colon"] != None:
59         e = data.createCopy()
60         bb.data.update_data(e)
61         val = bb.data.expand(groupd["value"], e)
62     elif "append" in groupd and groupd["append"] != None:
63         val = "%s %s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
64     elif "prepend" in groupd and groupd["prepend"] != None:
65         val = "%s %s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
66     elif "postdot" in groupd and groupd["postdot"] != None:
67         val = "%s%s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
68     elif "predot" in groupd and groupd["predot"] != None:
69         val = "%s%s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
70     else:
71         val = groupd["value"]
72     if 'flag' in groupd and groupd['flag'] != None:
73         bb.msg.debug(3, bb.msg.domain.Parsing, "setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
74         bb.data.setVarFlag(key, groupd['flag'], val, data)
75     else:
76         bb.data.setVar(key, val, data)
77
78 def getFunc(groupd, key, data):
79     if 'flag' in groupd and groupd['flag'] != None:
80         return bb.data.getVarFlag(key, groupd['flag'], data)
81     else:
82         return bb.data.getVar(key, data)
83
84 def handleMethod(statements, func_name, lineno, fn, body, d):
85     if func_name == "__anonymous":
86         funcname = ("__anon_%s_%s" % (lineno, fn.translate(string.maketrans('/.+-', '____'))))
87         if not funcname in bb.methodpool._parsed_fns:
88             text = "def %s(d):\n" % (funcname) + '\n'.join(body)
89             bb.methodpool.insert_method(funcname, text, fn)
90         anonfuncs = bb.data.getVar('__BBANONFUNCS', d) or []
91         anonfuncs.append(funcname)
92         bb.data.setVar('__BBANONFUNCS', anonfuncs, d)
93     else:
94         bb.data.setVarFlag(func_name, "func", 1, d)
95         bb.data.setVar(func_name, '\n'.join(body), d)
96
97 def handlePythonMethod(statements, root, body, fn):
98     # Note we will add root to parsedmethods after having parse
99     # 'this' file. This means we will not parse methods from
100     # bb classes twice
101     if not root in __parsed_methods__:
102         text = '\n'.join(body)
103         bb.methodpool.insert_method(root, text, fn)
104
105 def handleMethodFlags(statements, key, m, d):
106     if bb.data.getVar(key, d):
107         # Clean up old version of this piece of metadata, as its
108         # flags could cause problems
109         bb.data.setVarFlag(key, 'python', None, d)
110         bb.data.setVarFlag(key, 'fakeroot', None, d)
111     if m.group("py") is not None:
112         bb.data.setVarFlag(key, "python", "1", d)
113     else:
114         bb.data.delVarFlag(key, "python", d)
115     if m.group("fr") is not None:
116         bb.data.setVarFlag(key, "fakeroot", "1", d)
117     else:
118         bb.data.delVarFlag(key, "fakeroot", d)
119
120 def handleExportFuncs(statements, m, classes, d):
121     fns = m.group(1)
122     n = __word__.findall(fns)
123     for f in n:
124         allvars = []
125         allvars.append(f)
126         allvars.append(classes[-1] + "_" + f)
127
128         vars = [[ allvars[0], allvars[1] ]]
129         if len(classes) > 1 and classes[-2] is not None:
130             allvars.append(classes[-2] + "_" + f)
131             vars = []
132             vars.append([allvars[2], allvars[1]])
133             vars.append([allvars[0], allvars[2]])
134
135         for (var, calledvar) in vars:
136             if bb.data.getVar(var, d) and not bb.data.getVarFlag(var, 'export_func', d):
137                 continue
138
139             if bb.data.getVar(var, d):
140                 bb.data.setVarFlag(var, 'python', None, d)
141                 bb.data.setVarFlag(var, 'func', None, d)
142
143             for flag in [ "func", "python" ]:
144                 if bb.data.getVarFlag(calledvar, flag, d):
145                     bb.data.setVarFlag(var, flag, bb.data.getVarFlag(calledvar, flag, d), d)
146             for flag in [ "dirs" ]:
147                 if bb.data.getVarFlag(var, flag, d):
148                     bb.data.setVarFlag(calledvar, flag, bb.data.getVarFlag(var, flag, d), d)
149
150             if bb.data.getVarFlag(calledvar, "python", d):
151                 bb.data.setVar(var, "\tbb.build.exec_func('" + calledvar + "', d)\n", d)
152             else:
153                 bb.data.setVar(var, "\t" + calledvar + "\n", d)
154             bb.data.setVarFlag(var, 'export_func', '1', d)
155
156 def handleAddTask(statements, m, d):
157     func = m.group("func")
158     before = m.group("before")
159     after = m.group("after")
160     if func is None:
161         return
162     if func[:3] != "do_":
163         var = "do_" + func
164
165     bb.data.setVarFlag(var, "task", 1, d)
166
167     bbtasks = bb.data.getVar('__BBTASKS', d) or []
168     if not var in bbtasks:
169         bbtasks.append(var)
170     bb.data.setVar('__BBTASKS', bbtasks, d)
171
172     existing = bb.data.getVarFlag(var, "deps", d) or []
173     if after is not None:
174         # set up deps for function
175         for entry in after.split():
176             if entry not in existing:
177                 existing.append(entry)
178     bb.data.setVarFlag(var, "deps", existing, d)
179     if before is not None:
180         # set up things that depend on this func
181         for entry in before.split():
182             existing = bb.data.getVarFlag(entry, "deps", d) or []
183             if var not in existing:
184                 bb.data.setVarFlag(entry, "deps", [var] + existing, d)
185
186 def handleBBHandlers(statements, m, d):
187     fns = m.group(1)
188     hs = __word__.findall(fns)
189     bbhands = bb.data.getVar('__BBHANDLERS', d) or []
190     for h in hs:
191         bbhands.append(h)
192         bb.data.setVarFlag(h, "handler", 1, d)
193     bb.data.setVar('__BBHANDLERS', bbhands, d)
194
195 def handleInherit(statements, m, d):
196     files = m.group(1)
197     n = __word__.findall(files)
198     bb.parse.BBHandler.inherit(statements, n, d)
199