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