bitbake/lib/bb/data_smart.py: Double OVERRIDE expansion fix
[vuplus_bitbake] / lib / bb / data_smart.py
1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3 """
4 BitBake Smart Dictionary Implementation
5
6 Functions for interacting with the data structure used by the
7 BitBake build tools.
8
9 Copyright (C) 2003, 2004  Chris Larson
10 Copyright (C) 2004, 2005  Seb Frankengul
11 Copyright (C) 2005, 2006  Holger Hans Peter Freyther
12 Copyright (C) 2005        Uli Luckas
13 Copyright (C) 2005        ROAD GmbH
14
15 This program is free software; you can redistribute it and/or modify it under
16 the terms of the GNU General Public License as published by the Free Software
17 Foundation; either version 2 of the License, or (at your option) any later
18 version.
19
20 This program is distributed in the hope that it will be useful, but WITHOUT
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License along with
25 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26 Place, Suite 330, Boston, MA 02111-1307 USA. 
27
28 Based on functions from the base bb module, Copyright 2003 Holger Schurig
29 """
30
31 import copy, os, re, sys, time, types
32 from bb   import note, debug, error, fatal, utils, methodpool
33 from COW  import COWDictBase
34 from sets import Set
35 from new  import classobj
36
37
38 __setvar_keyword__ = ["_append","_prepend"]
39 __setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?')
40 __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
41 __expand_python_regexp__ = re.compile(r"\${@.+?}")
42
43
44 class DataSmart:
45     def __init__(self, special = COWDictBase.copy(), seen = COWDictBase.copy() ):
46         self.dict = {}
47
48         # cookie monster tribute
49         self._special_values = special
50         self._seen_overrides = seen
51
52     def expand(self,s, varname):
53         def var_sub(match):
54             key = match.group()[2:-1]
55             if varname and key:
56                 if varname == key:
57                     raise Exception("variable %s references itself!" % varname)
58             var = self.getVar(key, 1)
59             if var is not None:
60                 return var
61             else:
62                 return match.group()
63
64         def python_sub(match):
65             import bb
66             code = match.group()[3:-1]
67             locals()['d'] = self
68             s = eval(code)
69             if type(s) == types.IntType: s = str(s)
70             return s
71
72         if type(s) is not types.StringType: # sanity check
73             return s
74
75         while s.find('$') != -1:
76             olds = s
77             try:
78                 s = __expand_var_regexp__.sub(var_sub, s)
79                 s = __expand_python_regexp__.sub(python_sub, s)
80                 if s == olds: break
81                 if type(s) is not types.StringType: # sanity check
82                     error('expansion of %s returned non-string %s' % (olds, s))
83             except KeyboardInterrupt:
84                 raise
85             except:
86                 note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
87                 raise
88         return s
89
90     def initVar(self, var):
91         if not var in self.dict:
92             self.dict[var] = {}
93
94     def _findVar(self,var):
95         _dest = self.dict
96
97         while (_dest and var not in _dest):
98             if not "_data" in _dest:
99                 _dest = None
100                 break
101             _dest = _dest["_data"]
102
103         if _dest and var in _dest:
104             return _dest[var]
105         return None
106
107     def _makeShadowCopy(self, var):
108         if var in self.dict:
109             return
110
111         local_var = self._findVar(var)
112
113         if local_var:
114             self.dict[var] = copy.copy(local_var)
115         else:
116             self.initVar(var)
117
118     def setVar(self,var,value):
119         match  = __setvar_regexp__.match(var)
120         if match and match.group("keyword") in __setvar_keyword__:
121             base = match.group('base')
122             keyword = match.group("keyword")
123             override = match.group('add')
124             l = self.getVarFlag(base, keyword) or []
125             l.append([value, override])
126             self.setVarFlag(base, keyword, l)
127
128             # todo make sure keyword is not __doc__ or __module__
129             # pay the cookie monster
130             try:
131                 self._special_values[keyword].add( base )
132             except:
133                 self._special_values[keyword] = Set()
134                 self._special_values[keyword].add( base )
135
136             return
137
138         if not var in self.dict:
139             self._makeShadowCopy(var)
140         if self.getVarFlag(var, 'matchesenv'):
141             self.delVarFlag(var, 'matchesenv')
142             self.setVarFlag(var, 'export', 1)
143
144         # more cookies for the cookie monster
145         if '_' in var:
146             override = var[var.rfind('_')+1:]
147             if not self._seen_overrides.has_key(override):
148                 self._seen_overrides[override] = Set()
149             self._seen_overrides[override].add( var )
150
151         # setting var
152         self.dict[var]["content"] = value
153
154     def getVar(self,var,exp):
155         value = self.getVarFlag(var,"content")
156
157         if exp and value:
158             return self.expand(value,var)
159         return value
160
161     def delVar(self,var):
162         self.dict[var] = {}
163
164     def setVarFlag(self,var,flag,flagvalue):
165         if not var in self.dict:
166             self._makeShadowCopy(var)
167         self.dict[var][flag] = flagvalue
168
169     def getVarFlag(self,var,flag):
170         local_var = self._findVar(var)
171         if local_var:
172             if flag in local_var:
173                 return copy.copy(local_var[flag])
174         return None
175
176     def delVarFlag(self,var,flag):
177         local_var = self._findVar(var)
178         if not local_var:
179             return
180         if not var in self.dict:
181             self._makeShadowCopy(var)
182
183         if var in self.dict and flag in self.dict[var]:
184             del self.dict[var][flag]
185
186     def setVarFlags(self,var,flags):
187         if not var in self.dict:
188             self._makeShadowCopy(var)
189
190         for i in flags.keys():
191             if i == "content":
192                 continue
193             self.dict[var][i] = flags[i]
194
195     def getVarFlags(self,var):
196         local_var = self._findVar(var)
197         flags = {}
198
199         if local_var:
200             for i in self.dict[var].keys():
201                 if i == "content":
202                     continue
203                 flags[i] = self.dict[var][i]
204
205         if len(flags) == 0:
206             return None
207         return flags
208
209
210     def delVarFlags(self,var):
211         if not var in self.dict:
212             self._makeShadowCopy(var)
213
214         if var in self.dict:
215             content = None
216
217             # try to save the content
218             if "content" in self.dict[var]:
219                 content  = self.dict[var]["content"]
220                 self.dict[var]            = {}
221                 self.dict[var]["content"] = content
222             else:
223                 del self.dict[var]
224
225
226     def createCopy(self):
227         """
228         Create a copy of self by setting _data to self
229         """
230         # we really want this to be a DataSmart...
231         data = DataSmart(seen=self._seen_overrides.copy(), special=self._special_values.copy())
232         data.dict["_data"] = self.dict
233
234         return data
235
236     # Dictionary Methods
237     def keys(self):
238         def _keys(d, mykey):
239             if "_data" in d:
240                 _keys(d["_data"],mykey)
241
242             for key in d.keys():
243                 if key != "_data":
244                     mykey[key] = None
245         keytab = {}
246         _keys(self.dict,keytab)
247         return keytab.keys()
248
249     def __getitem__(self,item):
250         #print "Warning deprecated"
251         return self.getVar(item, False)
252
253     def __setitem__(self,var,data):
254         #print "Warning deprecated"
255         self.setVar(var,data)
256
257