1 | #! /usr/bin/env python |
---|
2 | # encoding: utf-8 |
---|
3 | # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file |
---|
4 | |
---|
5 | import re,string,traceback |
---|
6 | from waflib import Logs,Utils,Errors |
---|
7 | from waflib.Logs import debug,error |
---|
8 | class PreprocError(Errors.WafError): |
---|
9 | pass |
---|
10 | POPFILE='-' |
---|
11 | recursion_limit=150 |
---|
12 | go_absolute=False |
---|
13 | standard_includes=['/usr/include'] |
---|
14 | if Utils.is_win32: |
---|
15 | standard_includes=[] |
---|
16 | use_trigraphs=0 |
---|
17 | strict_quotes=0 |
---|
18 | g_optrans={'not':'!','not_eq':'!','and':'&&','and_eq':'&=','or':'||','or_eq':'|=','xor':'^','xor_eq':'^=','bitand':'&','bitor':'|','compl':'~',} |
---|
19 | re_lines=re.compile('^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$',re.IGNORECASE|re.MULTILINE) |
---|
20 | re_mac=re.compile("^[a-zA-Z_]\w*") |
---|
21 | re_fun=re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') |
---|
22 | re_pragma_once=re.compile('^\s*once\s*',re.IGNORECASE) |
---|
23 | re_nl=re.compile('\\\\\r*\n',re.MULTILINE) |
---|
24 | re_cpp=re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',re.DOTALL|re.MULTILINE) |
---|
25 | trig_def=[('??'+a,b)for a,b in zip("=-/!'()<>",r'#~\|^[]{}')] |
---|
26 | chr_esc={'0':0,'a':7,'b':8,'t':9,'n':10,'f':11,'v':12,'r':13,'\\':92,"'":39} |
---|
27 | NUM='i' |
---|
28 | OP='O' |
---|
29 | IDENT='T' |
---|
30 | STR='s' |
---|
31 | CHAR='c' |
---|
32 | tok_types=[NUM,STR,IDENT,OP] |
---|
33 | exp_types=[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]*)""",r'L?"([^"\\]|\\.)*"',r'[a-zA-Z_]\w*',r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]',] |
---|
34 | re_clexer=re.compile('|'.join(["(?P<%s>%s)"%(name,part)for name,part in zip(tok_types,exp_types)]),re.M) |
---|
35 | accepted='a' |
---|
36 | ignored='i' |
---|
37 | undefined='u' |
---|
38 | skipped='s' |
---|
39 | def repl(m): |
---|
40 | s=m.group(0) |
---|
41 | if s.startswith('/'): |
---|
42 | return' ' |
---|
43 | return s |
---|
44 | def filter_comments(filename): |
---|
45 | code=Utils.readf(filename) |
---|
46 | if use_trigraphs: |
---|
47 | for(a,b)in trig_def:code=code.split(a).join(b) |
---|
48 | code=re_nl.sub('',code) |
---|
49 | code=re_cpp.sub(repl,code) |
---|
50 | return[(m.group(2),m.group(3))for m in re.finditer(re_lines,code)] |
---|
51 | prec={} |
---|
52 | ops=['* / %','+ -','<< >>','< <= >= >','== !=','& | ^','&& ||',','] |
---|
53 | for x in range(len(ops)): |
---|
54 | syms=ops[x] |
---|
55 | for u in syms.split(): |
---|
56 | prec[u]=x |
---|
57 | def trimquotes(s): |
---|
58 | if not s:return'' |
---|
59 | s=s.rstrip() |
---|
60 | if s[0]=="'"and s[-1]=="'":return s[1:-1] |
---|
61 | return s |
---|
62 | def reduce_nums(val_1,val_2,val_op): |
---|
63 | try:a=0+val_1 |
---|
64 | except TypeError:a=int(val_1) |
---|
65 | try:b=0+val_2 |
---|
66 | except TypeError:b=int(val_2) |
---|
67 | d=val_op |
---|
68 | if d=='%':c=a%b |
---|
69 | elif d=='+':c=a+b |
---|
70 | elif d=='-':c=a-b |
---|
71 | elif d=='*':c=a*b |
---|
72 | elif d=='/':c=a/b |
---|
73 | elif d=='^':c=a^b |
---|
74 | elif d=='==':c=int(a==b) |
---|
75 | elif d=='|'or d=='bitor':c=a|b |
---|
76 | elif d=='||'or d=='or':c=int(a or b) |
---|
77 | elif d=='&'or d=='bitand':c=a&b |
---|
78 | elif d=='&&'or d=='and':c=int(a and b) |
---|
79 | elif d=='!='or d=='not_eq':c=int(a!=b) |
---|
80 | elif d=='^'or d=='xor':c=int(a^b) |
---|
81 | elif d=='<=':c=int(a<=b) |
---|
82 | elif d=='<':c=int(a<b) |
---|
83 | elif d=='>':c=int(a>b) |
---|
84 | elif d=='>=':c=int(a>=b) |
---|
85 | elif d=='<<':c=a<<b |
---|
86 | elif d=='>>':c=a>>b |
---|
87 | else:c=0 |
---|
88 | return c |
---|
89 | def get_num(lst): |
---|
90 | if not lst:raise PreprocError("empty list for get_num") |
---|
91 | (p,v)=lst[0] |
---|
92 | if p==OP: |
---|
93 | if v=='(': |
---|
94 | count_par=1 |
---|
95 | i=1 |
---|
96 | while i<len(lst): |
---|
97 | (p,v)=lst[i] |
---|
98 | if p==OP: |
---|
99 | if v==')': |
---|
100 | count_par-=1 |
---|
101 | if count_par==0: |
---|
102 | break |
---|
103 | elif v=='(': |
---|
104 | count_par+=1 |
---|
105 | i+=1 |
---|
106 | else: |
---|
107 | raise PreprocError("rparen expected %r"%lst) |
---|
108 | (num,_)=get_term(lst[1:i]) |
---|
109 | return(num,lst[i+1:]) |
---|
110 | elif v=='+': |
---|
111 | return get_num(lst[1:]) |
---|
112 | elif v=='-': |
---|
113 | num,lst=get_num(lst[1:]) |
---|
114 | return(reduce_nums('-1',num,'*'),lst) |
---|
115 | elif v=='!': |
---|
116 | num,lst=get_num(lst[1:]) |
---|
117 | return(int(not int(num)),lst) |
---|
118 | elif v=='~': |
---|
119 | num,lst=get_num(lst[1:]) |
---|
120 | return(~int(num),lst) |
---|
121 | else: |
---|
122 | raise PreprocError("Invalid op token %r for get_num"%lst) |
---|
123 | elif p==NUM: |
---|
124 | return v,lst[1:] |
---|
125 | elif p==IDENT: |
---|
126 | return 0,lst[1:] |
---|
127 | else: |
---|
128 | raise PreprocError("Invalid token %r for get_num"%lst) |
---|
129 | def get_term(lst): |
---|
130 | if not lst:raise PreprocError("empty list for get_term") |
---|
131 | num,lst=get_num(lst) |
---|
132 | if not lst: |
---|
133 | return(num,[]) |
---|
134 | (p,v)=lst[0] |
---|
135 | if p==OP: |
---|
136 | if v==',': |
---|
137 | return get_term(lst[1:]) |
---|
138 | elif v=='?': |
---|
139 | count_par=0 |
---|
140 | i=1 |
---|
141 | while i<len(lst): |
---|
142 | (p,v)=lst[i] |
---|
143 | if p==OP: |
---|
144 | if v==')': |
---|
145 | count_par-=1 |
---|
146 | elif v=='(': |
---|
147 | count_par+=1 |
---|
148 | elif v==':': |
---|
149 | if count_par==0: |
---|
150 | break |
---|
151 | i+=1 |
---|
152 | else: |
---|
153 | raise PreprocError("rparen expected %r"%lst) |
---|
154 | if int(num): |
---|
155 | return get_term(lst[1:i]) |
---|
156 | else: |
---|
157 | return get_term(lst[i+1:]) |
---|
158 | else: |
---|
159 | num2,lst=get_num(lst[1:]) |
---|
160 | if not lst: |
---|
161 | num2=reduce_nums(num,num2,v) |
---|
162 | return get_term([(NUM,num2)]+lst) |
---|
163 | p2,v2=lst[0] |
---|
164 | if p2!=OP: |
---|
165 | raise PreprocError("op expected %r"%lst) |
---|
166 | if prec[v2]>=prec[v]: |
---|
167 | num2=reduce_nums(num,num2,v) |
---|
168 | return get_term([(NUM,num2)]+lst) |
---|
169 | else: |
---|
170 | num3,lst=get_num(lst[1:]) |
---|
171 | num3=reduce_nums(num2,num3,v2) |
---|
172 | return get_term([(NUM,num),(p,v),(NUM,num3)]+lst) |
---|
173 | raise PreprocError("cannot reduce %r"%lst) |
---|
174 | def reduce_eval(lst): |
---|
175 | num,lst=get_term(lst) |
---|
176 | return(NUM,num) |
---|
177 | def stringize(lst): |
---|
178 | lst=[str(v2)for(p2,v2)in lst] |
---|
179 | return"".join(lst) |
---|
180 | def paste_tokens(t1,t2): |
---|
181 | p1=None |
---|
182 | if t1[0]==OP and t2[0]==OP: |
---|
183 | p1=OP |
---|
184 | elif t1[0]==IDENT and(t2[0]==IDENT or t2[0]==NUM): |
---|
185 | p1=IDENT |
---|
186 | elif t1[0]==NUM and t2[0]==NUM: |
---|
187 | p1=NUM |
---|
188 | if not p1: |
---|
189 | raise PreprocError('tokens do not make a valid paste %r and %r'%(t1,t2)) |
---|
190 | return(p1,t1[1]+t2[1]) |
---|
191 | def reduce_tokens(lst,defs,ban=[]): |
---|
192 | i=0 |
---|
193 | while i<len(lst): |
---|
194 | (p,v)=lst[i] |
---|
195 | if p==IDENT and v=="defined": |
---|
196 | del lst[i] |
---|
197 | if i<len(lst): |
---|
198 | (p2,v2)=lst[i] |
---|
199 | if p2==IDENT: |
---|
200 | if v2 in defs: |
---|
201 | lst[i]=(NUM,1) |
---|
202 | else: |
---|
203 | lst[i]=(NUM,0) |
---|
204 | elif p2==OP and v2=='(': |
---|
205 | del lst[i] |
---|
206 | (p2,v2)=lst[i] |
---|
207 | del lst[i] |
---|
208 | if v2 in defs: |
---|
209 | lst[i]=(NUM,1) |
---|
210 | else: |
---|
211 | lst[i]=(NUM,0) |
---|
212 | else: |
---|
213 | raise PreprocError("Invalid define expression %r"%lst) |
---|
214 | elif p==IDENT and v in defs: |
---|
215 | if isinstance(defs[v],str): |
---|
216 | a,b=extract_macro(defs[v]) |
---|
217 | defs[v]=b |
---|
218 | macro_def=defs[v] |
---|
219 | to_add=macro_def[1] |
---|
220 | if isinstance(macro_def[0],list): |
---|
221 | del lst[i] |
---|
222 | accu=to_add[:] |
---|
223 | reduce_tokens(accu,defs,ban+[v]) |
---|
224 | for x in range(len(accu)): |
---|
225 | lst.insert(i,accu[x]) |
---|
226 | i+=1 |
---|
227 | else: |
---|
228 | args=[] |
---|
229 | del lst[i] |
---|
230 | if i>=len(lst): |
---|
231 | raise PreprocError("expected '(' after %r (got nothing)"%v) |
---|
232 | (p2,v2)=lst[i] |
---|
233 | if p2!=OP or v2!='(': |
---|
234 | raise PreprocError("expected '(' after %r"%v) |
---|
235 | del lst[i] |
---|
236 | one_param=[] |
---|
237 | count_paren=0 |
---|
238 | while i<len(lst): |
---|
239 | p2,v2=lst[i] |
---|
240 | del lst[i] |
---|
241 | if p2==OP and count_paren==0: |
---|
242 | if v2=='(': |
---|
243 | one_param.append((p2,v2)) |
---|
244 | count_paren+=1 |
---|
245 | elif v2==')': |
---|
246 | if one_param:args.append(one_param) |
---|
247 | break |
---|
248 | elif v2==',': |
---|
249 | if not one_param:raise PreprocError("empty param in funcall %s"%v) |
---|
250 | args.append(one_param) |
---|
251 | one_param=[] |
---|
252 | else: |
---|
253 | one_param.append((p2,v2)) |
---|
254 | else: |
---|
255 | one_param.append((p2,v2)) |
---|
256 | if v2=='(':count_paren+=1 |
---|
257 | elif v2==')':count_paren-=1 |
---|
258 | else: |
---|
259 | raise PreprocError('malformed macro') |
---|
260 | accu=[] |
---|
261 | arg_table=macro_def[0] |
---|
262 | j=0 |
---|
263 | while j<len(to_add): |
---|
264 | (p2,v2)=to_add[j] |
---|
265 | if p2==OP and v2=='#': |
---|
266 | if j+1<len(to_add)and to_add[j+1][0]==IDENT and to_add[j+1][1]in arg_table: |
---|
267 | toks=args[arg_table[to_add[j+1][1]]] |
---|
268 | accu.append((STR,stringize(toks))) |
---|
269 | j+=1 |
---|
270 | else: |
---|
271 | accu.append((p2,v2)) |
---|
272 | elif p2==OP and v2=='##': |
---|
273 | if accu and j+1<len(to_add): |
---|
274 | t1=accu[-1] |
---|
275 | if to_add[j+1][0]==IDENT and to_add[j+1][1]in arg_table: |
---|
276 | toks=args[arg_table[to_add[j+1][1]]] |
---|
277 | if toks: |
---|
278 | accu[-1]=paste_tokens(t1,toks[0]) |
---|
279 | accu.extend(toks[1:]) |
---|
280 | else: |
---|
281 | accu.append((p2,v2)) |
---|
282 | accu.extend(toks) |
---|
283 | elif to_add[j+1][0]==IDENT and to_add[j+1][1]=='__VA_ARGS__': |
---|
284 | va_toks=[] |
---|
285 | st=len(macro_def[0]) |
---|
286 | pt=len(args) |
---|
287 | for x in args[pt-st+1:]: |
---|
288 | va_toks.extend(x) |
---|
289 | va_toks.append((OP,',')) |
---|
290 | if va_toks:va_toks.pop() |
---|
291 | if len(accu)>1: |
---|
292 | (p3,v3)=accu[-1] |
---|
293 | (p4,v4)=accu[-2] |
---|
294 | if v3=='##': |
---|
295 | accu.pop() |
---|
296 | if v4==','and pt<st: |
---|
297 | accu.pop() |
---|
298 | accu+=va_toks |
---|
299 | else: |
---|
300 | accu[-1]=paste_tokens(t1,to_add[j+1]) |
---|
301 | j+=1 |
---|
302 | else: |
---|
303 | accu.append((p2,v2)) |
---|
304 | elif p2==IDENT and v2 in arg_table: |
---|
305 | toks=args[arg_table[v2]] |
---|
306 | reduce_tokens(toks,defs,ban+[v]) |
---|
307 | accu.extend(toks) |
---|
308 | else: |
---|
309 | accu.append((p2,v2)) |
---|
310 | j+=1 |
---|
311 | reduce_tokens(accu,defs,ban+[v]) |
---|
312 | for x in range(len(accu)-1,-1,-1): |
---|
313 | lst.insert(i,accu[x]) |
---|
314 | i+=1 |
---|
315 | def eval_macro(lst,defs): |
---|
316 | reduce_tokens(lst,defs,[]) |
---|
317 | if not lst:raise PreprocError("missing tokens to evaluate") |
---|
318 | (p,v)=reduce_eval(lst) |
---|
319 | return int(v)!=0 |
---|
320 | def extract_macro(txt): |
---|
321 | t=tokenize(txt) |
---|
322 | if re_fun.search(txt): |
---|
323 | p,name=t[0] |
---|
324 | p,v=t[1] |
---|
325 | if p!=OP:raise PreprocError("expected open parenthesis") |
---|
326 | i=1 |
---|
327 | pindex=0 |
---|
328 | params={} |
---|
329 | prev='(' |
---|
330 | while 1: |
---|
331 | i+=1 |
---|
332 | p,v=t[i] |
---|
333 | if prev=='(': |
---|
334 | if p==IDENT: |
---|
335 | params[v]=pindex |
---|
336 | pindex+=1 |
---|
337 | prev=p |
---|
338 | elif p==OP and v==')': |
---|
339 | break |
---|
340 | else: |
---|
341 | raise PreprocError("unexpected token (3)") |
---|
342 | elif prev==IDENT: |
---|
343 | if p==OP and v==',': |
---|
344 | prev=v |
---|
345 | elif p==OP and v==')': |
---|
346 | break |
---|
347 | else: |
---|
348 | raise PreprocError("comma or ... expected") |
---|
349 | elif prev==',': |
---|
350 | if p==IDENT: |
---|
351 | params[v]=pindex |
---|
352 | pindex+=1 |
---|
353 | prev=p |
---|
354 | elif p==OP and v=='...': |
---|
355 | raise PreprocError("not implemented (1)") |
---|
356 | else: |
---|
357 | raise PreprocError("comma or ... expected (2)") |
---|
358 | elif prev=='...': |
---|
359 | raise PreprocError("not implemented (2)") |
---|
360 | else: |
---|
361 | raise PreprocError("unexpected else") |
---|
362 | return(name,[params,t[i+1:]]) |
---|
363 | else: |
---|
364 | (p,v)=t[0] |
---|
365 | if len(t)>1: |
---|
366 | return(v,[[],t[1:]]) |
---|
367 | else: |
---|
368 | return(v,[[],[('T','')]]) |
---|
369 | re_include=re.compile('^\s*(<(?P<a>.*)>|"(?P<b>.*)")') |
---|
370 | def extract_include(txt,defs): |
---|
371 | m=re_include.search(txt) |
---|
372 | if m: |
---|
373 | if m.group('a'):return'<',m.group('a') |
---|
374 | if m.group('b'):return'"',m.group('b') |
---|
375 | toks=tokenize(txt) |
---|
376 | reduce_tokens(toks,defs,['waf_include']) |
---|
377 | if not toks: |
---|
378 | raise PreprocError("could not parse include %s"%txt) |
---|
379 | if len(toks)==1: |
---|
380 | if toks[0][0]==STR: |
---|
381 | return'"',toks[0][1] |
---|
382 | else: |
---|
383 | if toks[0][1]=='<'and toks[-1][1]=='>': |
---|
384 | ret='<',stringize(toks).lstrip('<').rstrip('>') |
---|
385 | return ret |
---|
386 | raise PreprocError("could not parse include %s."%txt) |
---|
387 | def parse_char(txt): |
---|
388 | if not txt:raise PreprocError("attempted to parse a null char") |
---|
389 | if txt[0]!='\\': |
---|
390 | return ord(txt) |
---|
391 | c=txt[1] |
---|
392 | if c=='x': |
---|
393 | if len(txt)==4 and txt[3]in string.hexdigits:return int(txt[2:],16) |
---|
394 | return int(txt[2:],16) |
---|
395 | elif c.isdigit(): |
---|
396 | if c=='0'and len(txt)==2:return 0 |
---|
397 | for i in 3,2,1: |
---|
398 | if len(txt)>i and txt[1:1+i].isdigit(): |
---|
399 | return(1+i,int(txt[1:1+i],8)) |
---|
400 | else: |
---|
401 | try:return chr_esc[c] |
---|
402 | except KeyError:raise PreprocError("could not parse char literal '%s'"%txt) |
---|
403 | def tokenize(s): |
---|
404 | return tokenize_private(s)[:] |
---|
405 | @Utils.run_once |
---|
406 | def tokenize_private(s): |
---|
407 | ret=[] |
---|
408 | for match in re_clexer.finditer(s): |
---|
409 | m=match.group |
---|
410 | for name in tok_types: |
---|
411 | v=m(name) |
---|
412 | if v: |
---|
413 | if name==IDENT: |
---|
414 | try: |
---|
415 | g_optrans[v]; |
---|
416 | name=OP |
---|
417 | except KeyError: |
---|
418 | if v.lower()=="true": |
---|
419 | v=1 |
---|
420 | name=NUM |
---|
421 | elif v.lower()=="false": |
---|
422 | v=0 |
---|
423 | name=NUM |
---|
424 | elif name==NUM: |
---|
425 | if m('oct'):v=int(v,8) |
---|
426 | elif m('hex'):v=int(m('hex'),16) |
---|
427 | elif m('n0'):v=m('n0') |
---|
428 | else: |
---|
429 | v=m('char') |
---|
430 | if v:v=parse_char(v) |
---|
431 | else:v=m('n2')or m('n4') |
---|
432 | elif name==OP: |
---|
433 | if v=='%:':v='#' |
---|
434 | elif v=='%:%:':v='##' |
---|
435 | elif name==STR: |
---|
436 | v=v[1:-1] |
---|
437 | ret.append((name,v)) |
---|
438 | break |
---|
439 | return ret |
---|
440 | @Utils.run_once |
---|
441 | def define_name(line): |
---|
442 | return re_mac.match(line).group(0) |
---|
443 | class c_parser(object): |
---|
444 | def __init__(self,nodepaths=None,defines=None): |
---|
445 | self.lines=[] |
---|
446 | if defines is None: |
---|
447 | self.defs={} |
---|
448 | else: |
---|
449 | self.defs=dict(defines) |
---|
450 | self.state=[] |
---|
451 | self.count_files=0 |
---|
452 | self.currentnode_stack=[] |
---|
453 | self.nodepaths=nodepaths or[] |
---|
454 | self.nodes=[] |
---|
455 | self.names=[] |
---|
456 | self.curfile='' |
---|
457 | self.ban_includes=set([]) |
---|
458 | def cached_find_resource(self,node,filename): |
---|
459 | try: |
---|
460 | nd=node.ctx.cache_nd |
---|
461 | except AttributeError: |
---|
462 | nd=node.ctx.cache_nd={} |
---|
463 | tup=(node,filename) |
---|
464 | try: |
---|
465 | return nd[tup] |
---|
466 | except KeyError: |
---|
467 | ret=node.find_resource(filename) |
---|
468 | if ret: |
---|
469 | if getattr(ret,'children',None): |
---|
470 | ret=None |
---|
471 | elif ret.is_child_of(node.ctx.bldnode): |
---|
472 | tmp=node.ctx.srcnode.search_node(ret.path_from(node.ctx.bldnode)) |
---|
473 | if tmp and getattr(tmp,'children',None): |
---|
474 | ret=None |
---|
475 | nd[tup]=ret |
---|
476 | return ret |
---|
477 | def tryfind(self,filename): |
---|
478 | if filename.endswith('.moc'): |
---|
479 | self.names.append(filename) |
---|
480 | return None |
---|
481 | self.curfile=filename |
---|
482 | found=self.cached_find_resource(self.currentnode_stack[-1],filename) |
---|
483 | for n in self.nodepaths: |
---|
484 | if found: |
---|
485 | break |
---|
486 | found=self.cached_find_resource(n,filename) |
---|
487 | if found and not found in self.ban_includes: |
---|
488 | self.nodes.append(found) |
---|
489 | self.addlines(found) |
---|
490 | else: |
---|
491 | if not filename in self.names: |
---|
492 | self.names.append(filename) |
---|
493 | return found |
---|
494 | def addlines(self,node): |
---|
495 | self.currentnode_stack.append(node.parent) |
---|
496 | filepath=node.abspath() |
---|
497 | self.count_files+=1 |
---|
498 | if self.count_files>recursion_limit: |
---|
499 | raise PreprocError("recursion limit exceeded") |
---|
500 | pc=self.parse_cache |
---|
501 | debug('preproc: reading file %r',filepath) |
---|
502 | try: |
---|
503 | lns=pc[filepath] |
---|
504 | except KeyError: |
---|
505 | pass |
---|
506 | else: |
---|
507 | self.lines.extend(lns) |
---|
508 | return |
---|
509 | try: |
---|
510 | lines=filter_comments(filepath) |
---|
511 | lines.append((POPFILE,'')) |
---|
512 | lines.reverse() |
---|
513 | pc[filepath]=lines |
---|
514 | self.lines.extend(lines) |
---|
515 | except IOError: |
---|
516 | raise PreprocError("could not read the file %s"%filepath) |
---|
517 | except Exception: |
---|
518 | if Logs.verbose>0: |
---|
519 | error("parsing %s failed"%filepath) |
---|
520 | traceback.print_exc() |
---|
521 | def start(self,node,env): |
---|
522 | debug('preproc: scanning %s (in %s)',node.name,node.parent.name) |
---|
523 | bld=node.ctx |
---|
524 | try: |
---|
525 | self.parse_cache=bld.parse_cache |
---|
526 | except AttributeError: |
---|
527 | self.parse_cache=bld.parse_cache={} |
---|
528 | self.current_file=node |
---|
529 | self.addlines(node) |
---|
530 | if env['DEFINES']: |
---|
531 | try: |
---|
532 | lst=['%s %s'%(x[0],trimquotes('='.join(x[1:])))for x in[y.split('=')for y in env['DEFINES']]] |
---|
533 | lst.reverse() |
---|
534 | self.lines.extend([('define',x)for x in lst]) |
---|
535 | except AttributeError: |
---|
536 | pass |
---|
537 | while self.lines: |
---|
538 | (token,line)=self.lines.pop() |
---|
539 | if token==POPFILE: |
---|
540 | self.count_files-=1 |
---|
541 | self.currentnode_stack.pop() |
---|
542 | continue |
---|
543 | try: |
---|
544 | ve=Logs.verbose |
---|
545 | if ve:debug('preproc: line is %s - %s state is %s',token,line,self.state) |
---|
546 | state=self.state |
---|
547 | if token[:2]=='if': |
---|
548 | state.append(undefined) |
---|
549 | elif token=='endif': |
---|
550 | state.pop() |
---|
551 | if token[0]!='e': |
---|
552 | if skipped in self.state or ignored in self.state: |
---|
553 | continue |
---|
554 | if token=='if': |
---|
555 | ret=eval_macro(tokenize(line),self.defs) |
---|
556 | if ret:state[-1]=accepted |
---|
557 | else:state[-1]=ignored |
---|
558 | elif token=='ifdef': |
---|
559 | m=re_mac.match(line) |
---|
560 | if m and m.group(0)in self.defs:state[-1]=accepted |
---|
561 | else:state[-1]=ignored |
---|
562 | elif token=='ifndef': |
---|
563 | m=re_mac.match(line) |
---|
564 | if m and m.group(0)in self.defs:state[-1]=ignored |
---|
565 | else:state[-1]=accepted |
---|
566 | elif token=='include'or token=='import': |
---|
567 | (kind,inc)=extract_include(line,self.defs) |
---|
568 | if ve:debug('preproc: include found %s (%s) ',inc,kind) |
---|
569 | if kind=='"'or not strict_quotes: |
---|
570 | self.current_file=self.tryfind(inc) |
---|
571 | if token=='import': |
---|
572 | self.ban_includes.add(self.current_file) |
---|
573 | elif token=='elif': |
---|
574 | if state[-1]==accepted: |
---|
575 | state[-1]=skipped |
---|
576 | elif state[-1]==ignored: |
---|
577 | if eval_macro(tokenize(line),self.defs): |
---|
578 | state[-1]=accepted |
---|
579 | elif token=='else': |
---|
580 | if state[-1]==accepted:state[-1]=skipped |
---|
581 | elif state[-1]==ignored:state[-1]=accepted |
---|
582 | elif token=='define': |
---|
583 | try: |
---|
584 | self.defs[define_name(line)]=line |
---|
585 | except Exception: |
---|
586 | raise PreprocError("Invalid define line %s"%line) |
---|
587 | elif token=='undef': |
---|
588 | m=re_mac.match(line) |
---|
589 | if m and m.group(0)in self.defs: |
---|
590 | self.defs.__delitem__(m.group(0)) |
---|
591 | elif token=='pragma': |
---|
592 | if re_pragma_once.match(line.lower()): |
---|
593 | self.ban_includes.add(self.current_file) |
---|
594 | except Exception ,e: |
---|
595 | if Logs.verbose: |
---|
596 | debug('preproc: line parsing failed (%s): %s %s',e,line,Utils.ex_stack()) |
---|
597 | def scan(task): |
---|
598 | global go_absolute |
---|
599 | try: |
---|
600 | incn=task.generator.includes_nodes |
---|
601 | except AttributeError: |
---|
602 | raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": '%task.generator) |
---|
603 | if go_absolute: |
---|
604 | nodepaths=incn+[task.generator.bld.root.find_dir(x)for x in standard_includes] |
---|
605 | else: |
---|
606 | nodepaths=[x for x in incn if x.is_child_of(x.ctx.srcnode)or x.is_child_of(x.ctx.bldnode)] |
---|
607 | tmp=c_parser(nodepaths) |
---|
608 | tmp.start(task.inputs[0],task.env) |
---|
609 | if Logs.verbose: |
---|
610 | debug('deps: deps for %r: %r; unresolved %r'%(task.inputs,tmp.nodes,tmp.names)) |
---|
611 | return(tmp.nodes,tmp.names) |
---|