Release coccinelle-0.2.4
[bpt/coccinelle.git] / parsing_cocci / disjdistr.ml
CommitLineData
9bc82bae
C
1(*
2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
7 *
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
11 *
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
22 *)
23
24
c491d8ee
C
25(*
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
31 *
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
35 *
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
43 *
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
46 *)
47
48
34e49164
C
49module Ast = Ast_cocci
50module V = Visitor_ast
51
52let disjmult2 e1 e2 k =
53 List.concat
54 (List.map (function e1 -> List.map (function e2 -> k e1 e2) e2) e1)
55
56let disjmult3 e1 e2 e3 k =
57 List.concat
58 (List.map
59 (function e1 ->
60 List.concat
61 (List.map
62 (function e2 -> List.map (function e3 -> k e1 e2 e3) e3)
63 e2))
64 e1)
65
66let rec disjmult f = function
67 [] -> [[]]
68 | x::xs ->
69 let cur = f x in
70 let rest = disjmult f xs in
71 disjmult2 cur rest (function cur -> function rest -> cur :: rest)
72
73let disjoption f = function
74 None -> [None]
75 | Some x -> List.map (function x -> Some x) (f x)
76
77let disjdots f d =
78 match Ast.unwrap d with
79 Ast.DOTS(l) ->
80 List.map (function l -> Ast.rewrap d (Ast.DOTS(l))) (disjmult f l)
81 | Ast.CIRCLES(l) ->
82 List.map (function l -> Ast.rewrap d (Ast.CIRCLES(l))) (disjmult f l)
83 | Ast.STARS(l) ->
84 List.map (function l -> Ast.rewrap d (Ast.STARS(l))) (disjmult f l)
85
86let rec disjty ft =
87 match Ast.unwrap ft with
88 Ast.Type(cv,ty) ->
89 let ty = disjtypeC ty in
90 List.map (function ty -> Ast.rewrap ft (Ast.Type(cv,ty))) ty
91 | Ast.DisjType(types) -> List.concat (List.map disjty types)
92 | Ast.OptType(ty) ->
93 let ty = disjty ty in
94 List.map (function ty -> Ast.rewrap ft (Ast.OptType(ty))) ty
95 | Ast.UniqueType(ty) ->
96 let ty = disjty ty in
97 List.map (function ty -> Ast.rewrap ft (Ast.UniqueType(ty))) ty
98
99and disjtypeC bty =
100 match Ast.unwrap bty with
faf9a90c 101 Ast.BaseType(_) | Ast.SignedT(_,_) -> [bty]
34e49164
C
102 | Ast.Pointer(ty,star) ->
103 let ty = disjty ty in
104 List.map (function ty -> Ast.rewrap bty (Ast.Pointer(ty,star))) ty
105 | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
106 let ty = disjty ty in
107 List.map
108 (function ty ->
109 Ast.rewrap bty (Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2)))
110 ty
111 | Ast.FunctionType (s,ty,lp1,params,rp1) ->
112 let ty = disjoption disjty ty in
113 List.map
114 (function ty ->
115 Ast.rewrap bty (Ast.FunctionType (s,ty,lp1,params,rp1)))
116 ty
117 | Ast.Array(ty,lb,size,rb) ->
118 disjmult2 (disjty ty) (disjoption disjexp size)
119 (function ty -> function size ->
120 Ast.rewrap bty (Ast.Array(ty,lb,size,rb)))
faf9a90c 121 | Ast.EnumName(_,_) | Ast.StructUnionName(_,_) -> [bty]
c491d8ee
C
122 | Ast.EnumDef(ty,lb,ids,rb) ->
123 disjmult2 (disjty ty) (disjdots disjexp ids)
124 (function ty -> function ids ->
125 Ast.rewrap bty (Ast.EnumDef(ty,lb,ids,rb)))
34e49164
C
126 | Ast.StructUnionDef(ty,lb,decls,rb) ->
127 disjmult2 (disjty ty) (disjdots disjdecl decls)
128 (function ty -> function decls ->
129 Ast.rewrap bty (Ast.StructUnionDef(ty,lb,decls,rb)))
130 | Ast.TypeName(_) | Ast.MetaType(_,_,_) -> [bty]
131
132and disjexp e =
133 match Ast.unwrap e with
134 Ast.Ident(_) | Ast.Constant(_) -> [e]
135 | Ast.FunCall(fn,lp,args,rp) ->
136 disjmult2 (disjexp fn) (disjdots disjexp args)
137 (function fn -> function args ->
138 Ast.rewrap e (Ast.FunCall(fn,lp,args,rp)))
139 | Ast.Assignment(left,op,right,simple) ->
140 disjmult2 (disjexp left) (disjexp right)
141 (function left -> function right ->
142 Ast.rewrap e (Ast.Assignment(left,op,right,simple)))
143 | Ast.CondExpr(exp1,why,Some exp2,colon,exp3) ->
144 let res = disjmult disjexp [exp1;exp2;exp3] in
145 List.map
146 (function
147 [exp1;exp2;exp3] ->
148 Ast.rewrap e (Ast.CondExpr(exp1,why,Some exp2,colon,exp3))
149 | _ -> failwith "not possible")
150 res
151 | Ast.CondExpr(exp1,why,None,colon,exp3) ->
152 disjmult2 (disjexp exp1) (disjexp exp3)
153 (function exp1 -> function exp3 ->
154 Ast.rewrap e (Ast.CondExpr(exp1,why,None,colon,exp3)))
155 | Ast.Postfix(exp,op) ->
156 let exp = disjexp exp in
157 List.map (function exp -> Ast.rewrap e (Ast.Postfix(exp,op))) exp
158 | Ast.Infix(exp,op) ->
159 let exp = disjexp exp in
160 List.map (function exp -> Ast.rewrap e (Ast.Infix(exp,op))) exp
161 | Ast.Unary(exp,op) ->
162 let exp = disjexp exp in
163 List.map (function exp -> Ast.rewrap e (Ast.Unary(exp,op))) exp
164 | Ast.Binary(left,op,right) ->
165 disjmult2 (disjexp left) (disjexp right)
166 (function left -> function right ->
167 Ast.rewrap e (Ast.Binary(left,op,right)))
168 | Ast.Nested(exp,op,right) ->
169 (* disj not possible in right *)
170 let exp = disjexp exp in
171 List.map (function exp -> Ast.rewrap e (Ast.Nested(exp,op,right))) exp
172 | Ast.Paren(lp,exp,rp) ->
173 let exp = disjexp exp in
174 List.map (function exp -> Ast.rewrap e (Ast.Paren(lp,exp,rp))) exp
175 | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
176 disjmult2 (disjexp exp1) (disjexp exp2)
177 (function exp1 -> function exp2 ->
178 Ast.rewrap e (Ast.ArrayAccess(exp1,lb,exp2,rb)))
179 | Ast.RecordAccess(exp,pt,field) ->
180 let exp = disjexp exp in
181 List.map
182 (function exp -> Ast.rewrap e (Ast.RecordAccess(exp,pt,field))) exp
183 | Ast.RecordPtAccess(exp,ar,field) ->
184 let exp = disjexp exp in
185 List.map
186 (function exp -> Ast.rewrap e (Ast.RecordPtAccess(exp,ar,field))) exp
187 | Ast.Cast(lp,ty,rp,exp) ->
188 disjmult2 (disjty ty) (disjexp exp)
189 (function ty -> function exp -> Ast.rewrap e (Ast.Cast(lp,ty,rp,exp)))
190 | Ast.SizeOfExpr(szf,exp) ->
191 let exp = disjexp exp in
192 List.map (function exp -> Ast.rewrap e (Ast.SizeOfExpr(szf,exp))) exp
193 | Ast.SizeOfType(szf,lp,ty,rp) ->
194 let ty = disjty ty in
195 List.map
196 (function ty -> Ast.rewrap e (Ast.SizeOfType(szf,lp,ty,rp))) ty
197 | Ast.TypeExp(ty) ->
198 let ty = disjty ty in
199 List.map (function ty -> Ast.rewrap e (Ast.TypeExp(ty))) ty
200 | Ast.MetaErr(_,_,_,_) | Ast.MetaExpr(_,_,_,_,_,_)
201 | Ast.MetaExprList(_,_,_,_) | Ast.EComma(_) -> [e]
faf9a90c
C
202 | Ast.DisjExpr(exp_list) ->
203 List.concat (List.map disjexp exp_list)
5636bb2c 204 | Ast.NestExpr(starter,expr_dots,ender,whencode,multi) ->
34e49164
C
205 (* not sure what to do here, so ambiguities still possible *)
206 [e]
207 | Ast.Edots(dots,_) | Ast.Ecircles(dots,_) | Ast.Estars(dots,_) -> [e]
208 | Ast.OptExp(exp) ->
209 let exp = disjexp exp in
210 List.map (function exp -> Ast.rewrap e (Ast.OptExp(exp))) exp
211 | Ast.UniqueExp(exp) ->
212 let exp = disjexp exp in
213 List.map (function exp -> Ast.rewrap e (Ast.UniqueExp(exp))) exp
214
215and disjparam p =
216 match Ast.unwrap p with
217 Ast.VoidParam(ty) -> [p] (* void is the only possible value *)
218 | Ast.Param(ty,id) ->
219 let ty = disjty ty in
220 List.map (function ty -> Ast.rewrap p (Ast.Param(ty,id))) ty
221 | Ast.MetaParam(_,_,_) | Ast.MetaParamList(_,_,_,_) | Ast.PComma(_) -> [p]
222 | Ast.Pdots(dots) | Ast.Pcircles(dots) -> [p]
223 | Ast.OptParam(param) ->
224 let param = disjparam param in
225 List.map (function param -> Ast.rewrap p (Ast.OptParam(param))) param
226 | Ast.UniqueParam(param) ->
227 let param = disjparam param in
228 List.map (function param -> Ast.rewrap p (Ast.UniqueParam(param))) param
229
230and disjini i =
231 match Ast.unwrap i with
113803cf
C
232 Ast.MetaInit(_,_,_) -> [i]
233 | Ast.InitExpr(exp) ->
34e49164
C
234 let exp = disjexp exp in
235 List.map (function exp -> Ast.rewrap i (Ast.InitExpr(exp))) exp
c491d8ee
C
236 | Ast.ArInitList(lb,initlist,rb) ->
237 List.map
238 (function initlist ->
239 Ast.rewrap i (Ast.ArInitList(lb,initlist,rb)))
240 (disjdots disjini initlist)
241 | Ast.StrInitList(allminus,lb,initlist,rb,whencode) ->
34e49164
C
242 List.map
243 (function initlist ->
c491d8ee 244 Ast.rewrap i (Ast.StrInitList(allminus,lb,initlist,rb,whencode)))
34e49164 245 (disjmult disjini initlist)
113803cf
C
246 | Ast.InitGccExt(designators,eq,ini) ->
247 let designators = disjmult designator designators in
34e49164 248 let ini = disjini ini in
113803cf
C
249 disjmult2 designators ini
250 (function designators -> function ini ->
251 Ast.rewrap i (Ast.InitGccExt(designators,eq,ini)))
34e49164
C
252 | Ast.InitGccName(name,eq,ini) ->
253 let ini = disjini ini in
254 List.map
255 (function ini -> Ast.rewrap i (Ast.InitGccName(name,eq,ini)))
256 ini
34e49164 257 | Ast.IComma(comma) -> [i]
c491d8ee 258 | Ast.Idots(dots,_) -> [i]
faf9a90c 259 | Ast.OptIni(ini) ->
34e49164
C
260 let ini = disjini ini in
261 List.map (function ini -> Ast.rewrap i (Ast.OptIni(ini))) ini
faf9a90c 262 | Ast.UniqueIni(ini) ->
34e49164
C
263 let ini = disjini ini in
264 List.map (function ini -> Ast.rewrap i (Ast.UniqueIni(ini))) ini
265
113803cf
C
266and designator = function
267 Ast.DesignatorField(dot,id) -> [Ast.DesignatorField(dot,id)]
268 | Ast.DesignatorIndex(lb,exp,rb) ->
269 let exp = disjexp exp in
270 List.map (function exp -> Ast.DesignatorIndex(lb,exp,rb)) exp
271 | Ast.DesignatorRange(lb,min,dots,max,rb) ->
272 disjmult2 (disjexp min) (disjexp max)
273 (function min -> function max ->
274 Ast.DesignatorRange(lb,min,dots,max,rb))
275
34e49164
C
276and disjdecl d =
277 match Ast.unwrap d with
413ffc02
C
278 Ast.MetaDecl(_,_,_) | Ast.MetaField(_,_,_) -> [d]
279 | Ast.Init(stg,ty,id,eq,ini,sem) ->
34e49164
C
280 disjmult2 (disjty ty) (disjini ini)
281 (function ty -> function ini ->
282 Ast.rewrap d (Ast.Init(stg,ty,id,eq,ini,sem)))
283 | Ast.UnInit(stg,ty,id,sem) ->
284 let ty = disjty ty in
285 List.map (function ty -> Ast.rewrap d (Ast.UnInit(stg,ty,id,sem))) ty
286 | Ast.MacroDecl(name,lp,args,rp,sem) ->
287 List.map
288 (function args -> Ast.rewrap d (Ast.MacroDecl(name,lp,args,rp,sem)))
289 (disjdots disjexp args)
290 | Ast.TyDecl(ty,sem) ->
291 let ty = disjty ty in
292 List.map (function ty -> Ast.rewrap d (Ast.TyDecl(ty,sem))) ty
293 | Ast.Typedef(stg,ty,id,sem) ->
294 let ty = disjty ty in (* disj not allowed in id *)
295 List.map (function ty -> Ast.rewrap d (Ast.Typedef(stg,ty,id,sem))) ty
296 | Ast.DisjDecl(decls) -> List.concat (List.map disjdecl decls)
413ffc02 297 | Ast.Ddots(_,_) -> [d]
34e49164
C
298 | Ast.OptDecl(decl) ->
299 let decl = disjdecl decl in
300 List.map (function decl -> Ast.rewrap d (Ast.OptDecl(decl))) decl
301 | Ast.UniqueDecl(decl) ->
302 let decl = disjdecl decl in
303 List.map (function decl -> Ast.rewrap d (Ast.UniqueDecl(decl))) decl
304
305let generic_orify_rule_elem f re exp rebuild =
306 match f exp with
307 [exp] -> re
ae4735db 308 | orexps -> Ast.rewrap re (Ast.DisjRuleElem (List.map rebuild orexps))
34e49164
C
309
310let orify_rule_elem re exp rebuild =
311 generic_orify_rule_elem disjexp re exp rebuild
312
313let orify_rule_elem_ty = generic_orify_rule_elem disjty
314let orify_rule_elem_param = generic_orify_rule_elem disjparam
315let orify_rule_elem_decl = generic_orify_rule_elem disjdecl
1be43e12 316let orify_rule_elem_ini = generic_orify_rule_elem disjini
34e49164 317
fc1ad971 318let rec disj_rule_elem r k re =
faf9a90c 319 match Ast.unwrap re with
34e49164
C
320 Ast.FunHeader(bef,allminus,fninfo,name,lp,params,rp) ->
321 generic_orify_rule_elem (disjdots disjparam) re params
322 (function params ->
323 Ast.rewrap re
324 (Ast.FunHeader(bef,allminus,fninfo,name,lp,params,rp)))
325 | Ast.Decl(bef,allminus,decl) ->
326 orify_rule_elem_decl re decl
327 (function decl -> Ast.rewrap re (Ast.Decl(bef,allminus,decl)))
328 | Ast.SeqStart(brace) -> re
329 | Ast.SeqEnd(brace) -> re
330 | Ast.ExprStatement(exp,sem) ->
331 orify_rule_elem re exp
332 (function exp -> Ast.rewrap re (Ast.ExprStatement(exp,sem)))
333 | Ast.IfHeader(iff,lp,exp,rp) ->
334 orify_rule_elem re exp
335 (function exp -> Ast.rewrap re (Ast.IfHeader(iff,lp,exp,rp)))
336 | Ast.Else(els) -> re
337 | Ast.WhileHeader(whl,lp,exp,rp) ->
338 orify_rule_elem re exp
339 (function exp -> Ast.rewrap re (Ast.WhileHeader(whl,lp,exp,rp)))
340 | Ast.DoHeader(d) -> re
341 | Ast.WhileTail(whl,lp,exp,rp,sem) ->
342 orify_rule_elem re exp
343 (function exp -> Ast.rewrap re (Ast.WhileTail(whl,lp,exp,rp,sem)))
344 | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
345 generic_orify_rule_elem (disjmult (disjoption disjexp)) re [e1;e2;e3]
346 (function
347 [exp1;exp2;exp3] ->
348 Ast.rewrap re (Ast.ForHeader(fr,lp,exp1,sem1,exp2,sem2,exp3,rp))
349 | _ -> failwith "not possible")
350 | Ast.IteratorHeader(whl,lp,args,rp) ->
351 generic_orify_rule_elem (disjdots disjexp) re args
352 (function args -> Ast.rewrap re (Ast.IteratorHeader(whl,lp,args,rp)))
353 | Ast.SwitchHeader(switch,lp,exp,rp) ->
354 orify_rule_elem re exp
355 (function exp -> Ast.rewrap re (Ast.SwitchHeader(switch,lp,exp,rp)))
356 | Ast.Break(_,_) | Ast.Continue(_,_) | Ast.Label(_,_) | Ast.Goto(_,_,_)
357 | Ast.Return(_,_) -> re
358 | Ast.ReturnExpr(ret,exp,sem) ->
359 orify_rule_elem re exp
360 (function exp -> Ast.rewrap re (Ast.ReturnExpr(ret,exp,sem)))
361 | Ast.MetaRuleElem(_,_,_) | Ast.MetaStmt(_,_,_,_)
362 | Ast.MetaStmtList(_,_,_) -> re
363 | Ast.Exp(exp) ->
364 orify_rule_elem re exp (function exp -> Ast.rewrap exp (Ast.Exp(exp)))
365 | Ast.TopExp(exp) ->
366 orify_rule_elem re exp (function exp -> Ast.rewrap exp (Ast.TopExp(exp)))
367 | Ast.Ty(ty) ->
368 orify_rule_elem_ty re ty (function ty -> Ast.rewrap ty (Ast.Ty(ty)))
1be43e12
C
369 | Ast.TopInit(init) ->
370 orify_rule_elem_ini re init
371 (function init -> Ast.rewrap init (Ast.TopInit(init)))
34e49164
C
372 | Ast.Include(inc,s) -> re
373 | Ast.DefineHeader(def,id,params) -> re
374 | Ast.Default(def,colon) -> re
375 | Ast.Case(case,exp,colon) ->
376 orify_rule_elem re exp
377 (function exp -> Ast.rewrap re (Ast.Case(case,exp,colon)))
fc1ad971
C
378 | Ast.DisjRuleElem(l) ->
379 (* only case lines *)
ae4735db 380 Ast.rewrap re(Ast.DisjRuleElem(List.map (disj_rule_elem r k) l))
34e49164
C
381
382let disj_all =
383 let mcode x = x in
384 let donothing r k e = k e in
385 V.rebuilder
386 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
c491d8ee 387 donothing donothing donothing donothing donothing
34e49164
C
388 donothing donothing donothing donothing donothing donothing donothing
389 disj_rule_elem donothing donothing donothing donothing
390
391(* ----------------------------------------------------------------------- *)
392(* collect iso information at the rule_elem level *)
393
394let collect_all_isos =
395 let bind = (@) in
396 let option_default = [] in
397 let mcode r x = [] in
398 let donothing r k e = Common.union_set (Ast.get_isos e) (k e) in
399 let doanything r k e = k e in
400 V.combiner bind option_default
401 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164
C
402 donothing donothing donothing donothing donothing donothing donothing
403 donothing donothing donothing donothing donothing donothing donothing
c491d8ee 404 donothing donothing doanything
34e49164
C
405
406let collect_iso_info =
407 let mcode x = x in
408 let donothing r k e = k e in
409 let rule_elem r k e =
410 match Ast.unwrap e with
411 Ast.DisjRuleElem(l) -> k e
412 | _ ->
413 let isos = collect_all_isos.V.combiner_rule_elem e in
414 Ast.set_isos e isos in
415 V.rebuilder
416 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164 417 donothing donothing donothing donothing donothing donothing donothing
c491d8ee 418 donothing
34e49164
C
419 donothing donothing donothing donothing rule_elem donothing donothing
420 donothing donothing
421
422(* ----------------------------------------------------------------------- *)
423
424let disj rules =
425 List.map
426 (function (mv,r) ->
427 match r with
b1b2de81
C
428 Ast.ScriptRule _
429 | Ast.InitialScriptRule _ | Ast.FinalScriptRule _ -> (mv, r)
faf9a90c
C
430 | Ast.CocciRule (nm, rule_info, r, isexp, ruletype) ->
431 let res =
432 List.map
433 (function x ->
434 let res = disj_all.V.rebuilder_top_level x in
435 if !Flag.track_iso_usage
436 then collect_iso_info.V.rebuilder_top_level res
437 else res)
438 r in
439 (mv, Ast.CocciRule (nm,rule_info,res,isexp,ruletype)))
34e49164 440 rules