1
2
3
4
5
6
7
8 import re, sys, os, string, types
9 if __name__ == '__main__':
10 sys.path = ['.', '..'] + sys.path
11 import Logs, Build, Utils
12 from Logs import debug, error
13 import traceback
14
17
18 go_absolute = 0
19 "set to 1 to track headers on files in /usr/include - else absolute paths are ignored"
20
21 standard_includes = ['/usr/include']
22 if sys.platform == "win32":
23 standard_includes = []
24
25 use_trigraphs = 0
26 'apply the trigraph rules first'
27
28 strict_quotes = 0
29 "Keep <> for system includes (do not search for those includes)"
30
31 g_optrans = {
32 'not':'!',
33 'and':'&&',
34 'bitand':'&',
35 'and_eq':'&=',
36 'or':'||',
37 'bitor':'|',
38 'or_eq':'|=',
39 'xor':'^',
40 'xor_eq':'^=',
41 'compl':'~',
42 }
43 "these ops are for c++, to reset, set an empty dict"
44
45
46 re_lines = re.compile(\
47 '^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$',
48 re.IGNORECASE | re.MULTILINE)
49 re_mac = re.compile("^[a-zA-Z_]\w*")
50 re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]')
51 re_pragma_once = re.compile('^\s*once\s*', re.IGNORECASE)
52 re_nl = re.compile('\\\\\r*\n', re.MULTILINE)
53 re_cpp = re.compile(\
54 r"""(/\*[^*]*\*+([^/*][^*]*\*+)*/)|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)""",
55 re.MULTILINE)
56 trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')]
57 chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39}
58
59 NUM = 'i'
60 OP = 'O'
61 IDENT = 'T'
62 STR = 's'
63 CHAR = 'c'
64
65 tok_types = [NUM, STR, IDENT, OP]
66 exp_types = [
67 r"""0[xX](?P<hex>[a-fA-F0-9]+)(?P<qual1>[uUlL]*)|L*?'(?P<char>(\\.|[^\\'])+)'|(?P<n1>\d+)[Ee](?P<exp0>[+-]*?\d+)(?P<float0>[fFlL]*)|(?P<n2>\d*\.\d+)([Ee](?P<exp1>[+-]*?\d+))?(?P<float1>[fFlL]*)|(?P<n4>\d+\.\d*)([Ee](?P<exp2>[+-]*?\d+))?(?P<float2>[fFlL]*)|(?P<oct>0*)(?P<n0>\d+)(?P<qual2>[uUlL]*)""",
68 r'L?"([^"\\]|\\.)*"',
69 r'[a-zA-Z_]\w*',
70 r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]',
71 ]
72 re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M)
73
74 accepted = 'a'
75 ignored = 'i'
76 undefined = 'u'
77 skipped = 's'
78
80 s = m.group(1)
81 if s is not None: return ' '
82 s = m.group(3)
83 if s is None: return ''
84 return s
85
96
97 prec = {}
98
99 ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ',']
100 for x in range(len(ops)):
101 syms = ops[x]
102 for u in syms.split():
103 prec[u] = x
104
106
107
108
109
110 try: a = 0 + val_1
111 except TypeError: a = int(val_1)
112 try: b = 0 + val_2
113 except TypeError: b = int(val_2)
114
115 d = val_op
116 if d == '%': c = a%b
117 elif d=='+': c = a+b
118 elif d=='-': c = a-b
119 elif d=='*': c = a*b
120 elif d=='/': c = a/b
121 elif d=='^': c = a^b
122 elif d=='|': c = a|b
123 elif d=='||': c = int(a or b)
124 elif d=='&': c = a&b
125 elif d=='&&': c = int(a and b)
126 elif d=='==': c = int(a == b)
127 elif d=='!=': c = int(a != b)
128 elif d=='<=': c = int(a <= b)
129 elif d=='<': c = int(a < b)
130 elif d=='>': c = int(a > b)
131 elif d=='>=': c = int(a >= b)
132 elif d=='^': c = int(a^b)
133 elif d=='<<': c = a<<b
134 elif d=='>>': c = a>>b
135 else: c = 0
136 return c
137
139
140 if not lst: return ([], [], [])
141
142 (p, v) = lst[0]
143 if p == NUM:
144 return (p, v, lst[1:])
145
146 elif p == STR:
147 try:
148 (p2, v2) = lst[1]
149 if p2 == STR: return (p, v+v2, lst[2:])
150 except IndexError: pass
151
152 return (p, v, lst[1:])
153
154 elif p == OP:
155 if v in ['+', '-', '!', '~', '#']:
156 (p2, v2, lst2) = get_expr(lst[1:], defs, ban)
157
158 if v == '#':
159 if p2 != IDENT: raise PreprocError, "ident expected %s" % str(lst)
160 return get_expr([(STR, v2)]+lst2, defs, ban)
161
162 if p2 != NUM: raise PreprocError, "num expected %s" % str(lst)
163
164 if v == '+': return (p2, v2, lst2)
165 elif v == '-': return (p2, - int(v2), lst2)
166 elif v == '!': return (p2, int(not int(v2)), lst2)
167 elif v == '~': return (p2, ~ int(v2), lst2)
168
169 return (p2, v2, lst2)
170
171 elif v == '(':
172 count_par = 0
173 i = 0
174 for _, v in lst:
175 if v == ')':
176 count_par -= 1
177 if count_par == 0: break
178 elif v == '(': count_par += 1
179 i += 1
180 else:
181 raise PreprocError, "rparen expected %s" % str(lst)
182
183 ret = process_tokens(lst[1:i], defs, ban)
184 if len(ret) == 1:
185 (p, v) = ret[0]
186 return (p, v, lst[i+1:])
187 else:
188
189 raise PreprocError, "cannot reduce %s" % str(lst)
190
191 elif p == IDENT:
192 if len(lst)>1:
193 (p2, v2) = lst[1]
194 if v2 == "##":
195
196 (p3, v3) = lst[2]
197 if p3 != IDENT and p3 != NUM and p3 != OP:
198 raise PreprocError, "%s: ident expected after '##'" % str(lst)
199 return get_expr([(p, v+v3)]+lst[3:], defs, ban)
200
201 if v.lower() == 'defined':
202 (p2, v2) = lst[1]
203 off = 2
204 if v2 == '(':
205 (p3, v3) = lst[2]
206 if p3 != IDENT: raise PreprocError, 'expected an identifier after a "defined("'
207 (p2, v2) = lst[3]
208 if v2 != ')': raise PreprocError, 'expected a ")" after a "defined(x"'
209 off = 4
210 elif p2 != IDENT:
211 raise PreprocError, 'expected a "(" or an identifier after a defined'
212
213 x = 0
214 if v2 in defs: x = 1
215
216 return (NUM, x, lst[off:])
217
218 elif not v in defs or v in ban:
219 if "waf_include" in ban: return (p, v, lst[1:])
220 else: return (NUM, 0, lst[1:])
221
222
223 if type(defs[v]) is types.StringType:
224 v, k = extract_macro(defs[v])
225 defs[v] = k
226 macro_def = defs[v]
227
228 if not macro_def[0]:
229
230 lst = macro_def[1] + lst[1:]
231 return get_expr(lst, defs, ban)
232 else:
233
234 params = []
235 i = 1
236 p2, v2 = lst[i]
237 if p2 != OP or v2 != '(': raise PreprocError, "invalid function call '%s'" % v
238
239 one_param = []
240 count_paren = 0
241 try:
242 while 1:
243 i += 1
244 p2, v2 = lst[i]
245
246 if p2 == OP and count_paren == 0:
247 if v2 == '(':
248 one_param.append((p2, v2))
249 count_paren += 1
250 elif v2 == ')':
251 if one_param: params.append(one_param)
252 lst = lst[i+1:]
253 break
254 elif v2 == ',':
255 if not one_param: raise PreprocError, "empty param in funcall %s" % p
256 params.append(one_param)
257 one_param = []
258 else:
259 one_param.append((p2, v2))
260 else:
261 one_param.append((p2, v2))
262 if v2 == '(': count_paren += 1
263 elif v2 == ')': count_paren -= 1
264
265 except IndexError, e:
266
267 raise
268
269
270 accu = []
271 table = macro_def[0]
272 for p2, v2 in macro_def[1]:
273 if p2 == IDENT and v2 in table: accu += params[table[v2]]
274 else:
275 if v2 == '__VA_ARGS__':
276
277 va_toks = []
278 st = len(macro_def[0])
279 pt = len(params)
280 for x in params[pt-st+1:]:
281 va_toks.extend(x)
282 va_toks.append((OP, ','))
283 if va_toks: va_toks.pop()
284 if len(accu)>1:
285 (p3, v3) = accu[-1]
286 (p4, v4) = accu[-2]
287 if v3 == '##':
288
289 accu.pop()
290 if v4 == ',' and pt < st:
291
292 accu.pop()
293 accu += va_toks
294 else:
295 accu.append((p2, v2))
296
297 return get_expr(accu + lst, defs, ban+[v])
298
300 accu = []
301 while lst:
302 p, v, nlst = get_expr(lst, defs, ban)
303 if p == NUM:
304 if not nlst: return [(p, v)]
305
306 op1, ov1 = nlst[0]
307 if op1 != OP:
308 raise PreprocError, "op expected %s" % str(lst)
309
310 if ov1 == '?':
311 i = 0
312 count_par = 0
313 for _, k in nlst:
314 if k == ')': count_par -= 1
315 elif k == '(': count_par += 1
316 elif k == ':' and count_par == 0: break
317 i += 1
318 else: raise PreprocError, "ending ':' expected %s" % str(lst)
319
320 if reduce_nums(v, 0, '+'): lst = nlst[1:i]
321 else: lst = nlst[i+1:]
322 continue
323
324 elif ov1 == ',':
325 lst = nlst[1:]
326 continue
327
328 p2, v2, nlst = get_expr(nlst[1:], defs, ban)
329 if p2 != NUM: raise PreprocError, "num expected after op %s" % str(lst)
330 if nlst:
331
332 op3, ov3 = nlst[0]
333 if prec[ov3] < prec[ov1]:
334
335
336 p4, v4, nlst2 = get_expr(nlst[1:], defs, ban)
337 v5 = reduce_nums(v2, v4, ov3)
338 lst = [(p, v), (op1, ov1), (NUM, v5)] + nlst2
339 continue
340
341
342 lst = [(NUM, reduce_nums(v, v2, ov1))] + nlst
343 continue
344
345 elif p == STR:
346 if nlst: raise PreprocError, "sequence must terminate with a string %s" % str(nlst)
347 return [(p, v)]
348
349 return (None, None, [])
350
352
353 ret = process_tokens(lst, adefs, [])
354 if not ret: raise PreprocError, "missing tokens to evaluate %s" % str(lst)
355 p, v = ret[0]
356 return int(v) != 0
357
359 - def __init__(self, nodepaths=None, defines=None):
360
361 self.lines = []
362
363 if defines is None:
364 self.defs = {}
365 else:
366 self.defs = dict(defines)
367