Coccinelle release-1.0.0-rc11
[bpt/coccinelle.git] / parsing_cocci / single_statement.ml
CommitLineData
f537ebc4 1(*
17ba0788
C
2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
f537ebc4
C
5 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
6 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
7 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
8 * This file is part of Coccinelle.
9 *
10 * Coccinelle is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, according to version 2 of the License.
13 *
14 * Coccinelle is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
24 *)
25
26
34e49164
C
27(* detect statements that are between dots in the minus code, because they
28may need a special treatment if they are if branches *)
29
30module Ast0 = Ast0_cocci
31module Ast = Ast_cocci
32module V0 = Visitor_ast0
b1b2de81 33module VT0 = Visitor_ast0_types
34e49164
C
34
35(* --------------------------------------------------------------------- *)
36(* --------------------------------------------------------------------- *)
37(* Helpers *)
38
39let left_dots f l =
40 match Ast0.undots l with
41 [] -> false
42 | x::xs -> f x
43
44let right_dots f l =
45 match List.rev (Ast0.undots l) with
46 [] -> false
47 | x::xs -> f x
48
49let modif_before_mcode mc =
50 match Ast0.get_mcode_mcodekind mc with
51 Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
951c7801 52 | Ast0.PLUS _ -> failwith "not possible"
34e49164
C
53 | Ast0.CONTEXT mc ->
54 (match !mc with
55 (Ast.BEFORE _,_,_) -> true
56 | (Ast.BEFOREAFTER _,_,_) -> true
57 | _ -> false)
58 | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
59
60let modif_after_mcodekind = function
61 Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
951c7801 62 | Ast0.PLUS _ -> failwith "not possible"
34e49164
C
63 | Ast0.CONTEXT mc ->
64 (match !mc with
65 (Ast.AFTER _,_,_) -> true
66 | (Ast.BEFOREAFTER _,_,_) -> true
67 | _ -> false)
68 | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
69
70let modif_after_mcode mc = modif_after_mcodekind (Ast0.get_mcode_mcodekind mc)
71
72let any_statements =
73 List.exists
74 (List.exists
75 (function
76 Ast.StatementTag(_) | Ast.StmtDotsTag(_)
77 | Ast.DeclarationTag(_) | Ast.DeclDotsTag(_) -> true | _ -> false))
78
79let modif_before x =
80 match Ast0.get_mcodekind x with
951c7801 81 Ast0.PLUS _ -> failwith "not possible"
34e49164
C
82 | Ast0.MINUS mc ->
83 (match !mc with
84 (* do better for the common case of replacing a stmt by another one *)
8babbc8f 85 ((Ast.REPLACEMENT([[Ast.StatementTag(s)]],c)) as old,ti) ->
34e49164
C
86 (match Ast.unwrap s with
87 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
8babbc8f 88 | _ -> mc := (old,ti); false)
34e49164
C
89 | (_,_) -> true)
90 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
91 (match !mc with
92 (Ast.BEFORE _,_,_) -> true
93 | (Ast.BEFOREAFTER _,_,_) -> true
94 | _ -> false)
95
96let modif_after x =
97 match Ast0.get_mcodekind x with
951c7801 98 Ast0.PLUS _ -> failwith "not possible"
34e49164
C
99 | Ast0.MINUS mc ->
100 (match !mc with
101 (* do better for the common case of replacing a stmt by another one *)
8babbc8f 102 ((Ast.REPLACEMENT([[Ast.StatementTag(s)]],count)) as old,ti) ->
34e49164
C
103 (match Ast.unwrap s with
104 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
8babbc8f
C
105 | _ -> mc := (old,ti); false)
106 | (Ast.REPLACEMENT(l,_),_) when any_statements l -> true
951c7801 107 | (l,ti) -> mc := (l,ti); false)
34e49164
C
108 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
109 (match !mc with
110 (Ast.AFTER _,_,_) -> true
111 | (Ast.BEFOREAFTER _,_,_) -> true
faf9a90c 112 | _ -> false)
34e49164
C
113
114(* Identifier *)
115let rec left_ident i =
116 modif_before i or
117 match Ast0.unwrap i with
118 Ast0.Id(name) -> modif_before_mcode name
8babbc8f 119 | Ast0.MetaId(name,_,_,_) -> modif_before_mcode name
34e49164
C
120 | Ast0.MetaFunc(name,_,_) -> modif_before_mcode name
121 | Ast0.MetaLocalFunc(name,_,_) -> modif_before_mcode name
d3f655c6 122 | Ast0.DisjId(_,id_list,_,_) -> List.exists left_ident id_list
34e49164
C
123 | Ast0.OptIdent(id) -> left_ident id
124 | Ast0.UniqueIdent(id) -> left_ident id
125
3a314143
C
126let rec right_ident i =
127 modif_after i or
128 match Ast0.unwrap i with
129 Ast0.Id(name) -> modif_after_mcode name
8babbc8f 130 | Ast0.MetaId(name,_,_,_) -> modif_after_mcode name
3a314143
C
131 | Ast0.MetaFunc(name,_,_) -> modif_after_mcode name
132 | Ast0.MetaLocalFunc(name,_,_) -> modif_after_mcode name
d3f655c6 133 | Ast0.DisjId(_,id_list,_,_) -> List.exists right_ident id_list
3a314143
C
134 | Ast0.OptIdent(id) -> right_ident id
135 | Ast0.UniqueIdent(id) -> right_ident id
136
34e49164
C
137(* --------------------------------------------------------------------- *)
138(* Expression *)
139
140let rec left_expression e =
141 modif_before e or
142 match Ast0.unwrap e with
143 Ast0.Ident(id) -> left_ident id
144 | Ast0.Constant(const) -> modif_before_mcode const
145 | Ast0.FunCall(fn,lp,args,rp) -> left_expression fn
146 | Ast0.Assignment(left,op,right,_) -> left_expression left
17ba0788 147 | Ast0.Sequence(left,op,right) -> left_expression left
34e49164
C
148 | Ast0.CondExpr(exp1,why,exp2,colon,exp3) -> left_expression exp1
149 | Ast0.Postfix(exp,op) -> left_expression exp
150 | Ast0.Infix(exp,op) -> modif_before_mcode op
151 | Ast0.Unary(exp,op) -> modif_before_mcode op
152 | Ast0.Binary(left,op,right) -> left_expression left
153 | Ast0.Nested(left,op,right) -> left_expression left
154 | Ast0.Paren(lp,exp,rp) -> modif_before_mcode lp
155 | Ast0.ArrayAccess(exp1,lb,exp2,rb) -> left_expression exp1
156 | Ast0.RecordAccess(exp,pt,field) -> left_expression exp
157 | Ast0.RecordPtAccess(exp,ar,field) -> left_expression exp
158 | Ast0.Cast(lp,ty,rp,exp) -> modif_before_mcode lp
159 | Ast0.SizeOfExpr(szf,exp) -> modif_before_mcode szf
160 | Ast0.SizeOfType(szf,lp,ty,rp) -> modif_before_mcode szf
161 | Ast0.TypeExp(ty) -> left_typeC ty
7fe62b65 162 | Ast0.Constructor(lp,ty,rp,init) -> modif_before_mcode lp
34e49164
C
163 | Ast0.MetaErr(name,_,_) -> modif_before_mcode name
164 | Ast0.MetaExpr(name,_,ty,_,_) -> modif_before_mcode name
165 | Ast0.MetaExprList(name,_,_) -> modif_before_mcode name
166 | Ast0.EComma(cm) -> modif_before_mcode cm
167 | Ast0.DisjExpr(_,exp_list,_,_) -> List.exists left_expression exp_list
168 | Ast0.NestExpr(starter,expr_dots,ender,_,multi) ->
169 left_dots left_expression expr_dots
170 | Ast0.Edots(dots,_) | Ast0.Ecircles(dots,_) | Ast0.Estars(dots,_) -> false
171 | Ast0.OptExp(exp) -> left_expression exp
172 | Ast0.UniqueExp(exp) -> left_expression exp
17ba0788 173 | Ast0.AsExpr _ -> failwith "not possible"
34e49164
C
174
175(* --------------------------------------------------------------------- *)
176(* Types *)
177
178and left_typeC t =
179 modif_before t or
180 match Ast0.unwrap t with
181 Ast0.ConstVol(cv,ty) -> modif_before_mcode cv
faf9a90c
C
182 | Ast0.BaseType(ty,strings) -> modif_before_mcode (List.hd strings)
183 | Ast0.Signed(sgn,ty) -> modif_before_mcode sgn
34e49164
C
184 | Ast0.Pointer(ty,star) -> left_typeC ty
185 | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> left_typeC ty
186 | Ast0.FunctionType(Some ty,lp1,params,rp1) -> left_typeC ty
187 | Ast0.FunctionType(None,lp1,params,rp1) -> modif_before_mcode lp1
188 | Ast0.Array(ty,lb,size,rb) -> left_typeC ty
faf9a90c 189 | Ast0.EnumName(kind,name) -> modif_before_mcode kind
c491d8ee 190 | Ast0.EnumDef(ty,lb,ids,rb) -> left_typeC ty
34e49164
C
191 | Ast0.StructUnionName(kind,name) -> modif_before_mcode kind
192 | Ast0.StructUnionDef(ty,lb,decls,rb) -> left_typeC ty
193 | Ast0.TypeName(name) -> modif_before_mcode name
194 | Ast0.MetaType(name,_) -> modif_before_mcode name
195 | Ast0.DisjType(lp,types,mids,rp) -> List.exists left_typeC types
196 | Ast0.OptType(ty) -> left_typeC ty
197 | Ast0.UniqueType(ty) -> left_typeC ty
17ba0788
C
198 | Ast0.AsType _ -> failwith "not possible"
199
34e49164
C
200
201(* --------------------------------------------------------------------- *)
202(* Variable declaration *)
203(* Even if the Cocci program specifies a list of declarations, they are
204 split out into multiple declarations of a single variable each. *)
205
206and left_declaration d =
207 modif_before d or
208 match Ast0.unwrap d with
190f1acf
C
209 Ast0.MetaDecl(name,_) | Ast0.MetaField(name,_)
210 | Ast0.MetaFieldList(name,_,_) ->
211 modif_before_mcode name
413ffc02 212 | Ast0.Init(Some stg,ty,id,eq,ini,sem) -> modif_before_mcode stg
34e49164
C
213 | Ast0.Init(None,ty,id,eq,ini,sem) -> left_typeC ty
214 | Ast0.UnInit(Some stg,ty,id,sem) -> modif_before_mcode stg
215 | Ast0.UnInit(None,ty,id,sem) -> left_typeC ty
216 | Ast0.MacroDecl(name,lp,args,rp,sem) -> left_ident name
17ba0788 217 | Ast0.MacroDeclInit(name,lp,args,rp,eq,ini,sem) -> left_ident name
34e49164
C
218 | Ast0.TyDecl(ty,sem) -> left_typeC ty
219 | Ast0.Typedef(stg,ty,id,sem) -> modif_before_mcode stg
220 | Ast0.DisjDecl(_,decls,_,_) -> List.exists left_declaration decls
221 | Ast0.Ddots(dots,_) -> false
222 | Ast0.OptDecl(decl) -> left_declaration decl
223 | Ast0.UniqueDecl(decl) -> left_declaration decl
17ba0788 224 | Ast0.AsDecl _ -> failwith "not possible"
34e49164
C
225
226and right_declaration d =
227 modif_before d or
228 match Ast0.unwrap d with
190f1acf
C
229 Ast0.MetaDecl(name,_) | Ast0.MetaField(name,_)
230 | Ast0.MetaFieldList(name,_,_) ->
231 modif_before_mcode name
413ffc02 232 | Ast0.Init(_,ty,id,eq,ini,sem) -> modif_after_mcode sem
34e49164
C
233 | Ast0.UnInit(_,ty,id,sem) -> modif_after_mcode sem
234 | Ast0.MacroDecl(name,lp,args,rp,sem) -> modif_after_mcode sem
17ba0788 235 | Ast0.MacroDeclInit(name,lp,args,rp,eq,ini,sem) -> modif_after_mcode sem
34e49164
C
236 | Ast0.TyDecl(ty,sem) -> modif_after_mcode sem
237 | Ast0.Typedef(stg,ty,id,sem) -> modif_after_mcode sem
238 | Ast0.DisjDecl(_,decls,_,_) -> List.exists right_declaration decls
239 | Ast0.Ddots(dots,_) -> false
240 | Ast0.OptDecl(decl) -> right_declaration decl
241 | Ast0.UniqueDecl(decl) -> right_declaration decl
17ba0788 242 | Ast0.AsDecl _ -> failwith "not possible"
34e49164
C
243
244(* --------------------------------------------------------------------- *)
245(* Top-level code *)
246
247and left_statement s =
248 modif_before s or
249 match Ast0.unwrap s with
250 Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
251 (* irrelevant *) false
252 | Ast0.Decl(_,decl) -> left_declaration decl
253 | Ast0.Seq(lbrace,body,rbrace) -> modif_before_mcode lbrace
8babbc8f
C
254 | Ast0.ExprStatement(Some exp,sem) -> left_expression exp
255 | Ast0.ExprStatement(None,sem) -> modif_before_mcode sem
34e49164
C
256 | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_before_mcode iff
257 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
258 modif_before_mcode iff
259 | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_before_mcode whl
260 | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_before_mcode d
261 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
262 modif_before_mcode fr
263 | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) -> left_ident nm
fc1ad971
C
264 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
265 modif_before_mcode switch
34e49164
C
266 | Ast0.Break(br,sem) -> modif_before_mcode br
267 | Ast0.Continue(cont,sem) -> modif_before_mcode cont
268 | Ast0.Label(l,dd) -> left_ident l
269 | Ast0.Goto(goto,l,sem) -> modif_before_mcode goto
270 | Ast0.Return(ret,sem) -> modif_before_mcode ret
271 | Ast0.ReturnExpr(ret,exp,sem) -> modif_before_mcode ret
272 | Ast0.MetaStmt(name,pure) -> modif_before_mcode name
273 | Ast0.MetaStmtList(name,_) -> modif_before_mcode name
274 | Ast0.Disj(_,statement_dots_list,_,_) ->
275 List.exists (left_dots left_statement) statement_dots_list
276 | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
277 left_dots left_statement stmt_dots
278 | Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
279 | Ast0.TopExp(exp) -> false (* as above *)
280 | Ast0.Ty(ty) -> false (* can only be replaced by a type *)
1be43e12 281 | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
34e49164
C
282 | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
283 | Ast0.Include(inc,s) -> modif_before_mcode inc
3a314143 284 | Ast0.Undef(def,id) -> modif_before_mcode def
34e49164
C
285 | Ast0.Define(def,id,params,body) -> modif_before_mcode def
286 | Ast0.OptStm(re) -> left_statement re
287 | Ast0.UniqueStm(re) -> left_statement re
17ba0788 288 | Ast0.AsStmt _ -> failwith "not possible"
34e49164
C
289
290and right_statement s =
291 modif_after s or
292 match Ast0.unwrap s with
293 Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
294 (* irrelevant *) false
295 | Ast0.Decl(_,decl) -> right_declaration decl
296 | Ast0.Seq(lbrace,body,rbrace) -> modif_after_mcode rbrace
297 | Ast0.ExprStatement(exp,sem) -> modif_after_mcode sem
298 | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_after_mcodekind aft
299 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
300 modif_after_mcodekind aft
301 | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_after_mcodekind aft
302 | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_after_mcode sem
303 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
304 modif_after_mcodekind aft
305 | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) ->
306 modif_after_mcodekind aft
fc1ad971 307 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) -> modif_after_mcode rb
34e49164
C
308 | Ast0.Break(br,sem) -> modif_after_mcode sem
309 | Ast0.Continue(cont,sem) -> modif_after_mcode sem
310 | Ast0.Label(l,dd) -> modif_after_mcode dd
311 | Ast0.Goto(goto,l,sem) -> modif_after_mcode sem
312 | Ast0.Return(ret,sem) -> modif_after_mcode sem
313 | Ast0.ReturnExpr(ret,exp,sem) -> modif_after_mcode sem
314 | Ast0.MetaStmt(name,pure) -> modif_after_mcode name
315 | Ast0.MetaStmtList(name,_) -> modif_after_mcode name
316 | Ast0.Disj(_,statement_dots_list,_,_) ->
317 List.exists (right_dots right_statement) statement_dots_list
318 | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
319 right_dots right_statement stmt_dots
320 | Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
321 | Ast0.TopExp(exp) -> false (* as above *)
322 | Ast0.Ty(ty) -> false (* can only be replaced by a type *)
1be43e12 323 | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
34e49164
C
324 | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
325 | Ast0.Include(inc,s) -> modif_after_mcode s
3a314143 326 | Ast0.Undef(def,id) -> right_ident id
34e49164
C
327 | Ast0.Define(def,id,params,body) -> right_dots right_statement body
328 | Ast0.OptStm(re) -> right_statement re
329 | Ast0.UniqueStm(re) -> right_statement re
17ba0788 330 | Ast0.AsStmt _ -> failwith "not possible"
34e49164
C
331
332(* --------------------------------------------------------------------- *)
333
334
335(* A very coarse approximation. We would really only like to return true
336if a new statement is added. For this it would be best to correlate with the
337plus slice. Or at least be sure that the new stuff is on the far left or
338far right. *)
339
340let rec adding_something s =
341 match Ast0.get_mcodekind s with
342 Ast0.MINUS(mc) ->
343 (match !mc with
344 (* do better for the common case of replacing a stmt by another one *)
8babbc8f 345 ((Ast.REPLACEMENT([[Ast.StatementTag(s)]],c)) as old,ti) ->
34e49164
C
346 (match Ast.unwrap s with
347 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
8babbc8f 348 | _ -> mc := (old,ti); false)
34e49164
C
349 | (_,_) -> true)
350 | Ast0.CONTEXT(mc) ->
351 let (text,tinfo1,tinfo2) = !mc in
352 (match text with Ast.NOTHING -> false | _ -> true)
353 | Ast0.MIXED(_) ->
b1b2de81 354 not(contains_only_minus.VT0.combiner_rec_statement s) (*&&
34e49164
C
355 (left_statement s) or (right_statement s)*)
356 | _ -> failwith "unexpected plus code"
357
358(* why do we need this; MINUS should mean the same thing *)
359and contains_only_minus =
360 let bind x y = x && y in
361 let option_default = true in
362 let mcodekind = function
363 Ast0.MINUS(mc) ->
364 (match !mc with
8babbc8f 365 (Ast.NOREPLACEMENT,_) -> true
34e49164
C
366 | _ -> false)
367 | Ast0.CONTEXT(mc) -> false
368 | _ -> false in
708f4980 369 let mcode (_,_,_,mc,_,_) = mcodekind mc in
34e49164
C
370
371 let donothing r k e = mcodekind (Ast0.get_mcodekind e) && k e in
372
373 let dots r k e =
374 match Ast0.unwrap e with
375 Ast0.DOTS([]) | Ast0.CIRCLES([]) | Ast0.STARS([]) -> true
376 | _ -> k e in
377
d3f655c6
C
378 let identifier r k e =
379 mcodekind (Ast0.get_mcodekind e) &&
380 match Ast0.unwrap e with
381 Ast0.DisjId(starter,id_list,mids,ender) ->
382 List.for_all r.VT0.combiner_rec_ident id_list
383 | _ -> k e in
384
34e49164
C
385 let expression r k e =
386 mcodekind (Ast0.get_mcodekind e) &&
387 match Ast0.unwrap e with
388 Ast0.DisjExpr(starter,expr_list,mids,ender) ->
b1b2de81 389 List.for_all r.VT0.combiner_rec_expression expr_list
34e49164
C
390 | _ -> k e in
391
392 let declaration r k e =
393 mcodekind (Ast0.get_mcodekind e) &&
394 match Ast0.unwrap e with
395 Ast0.DisjDecl(starter,decls,mids,ender) ->
b1b2de81 396 List.for_all r.VT0.combiner_rec_declaration decls
34e49164
C
397 | _ -> k e in
398
399 let typeC r k e =
400 mcodekind (Ast0.get_mcodekind e) &&
401 match Ast0.unwrap e with
402 Ast0.DisjType(starter,types,mids,ender) ->
b1b2de81 403 List.for_all r.VT0.combiner_rec_typeC types
34e49164
C
404 | _ -> k e in
405
406 let statement r k e =
407 mcodekind (Ast0.get_mcodekind e) &&
408 match Ast0.unwrap e with
409 Ast0.Disj(starter,statement_dots_list,mids,ender) ->
b1b2de81 410 List.for_all r.VT0.combiner_rec_statement_dots statement_dots_list
34e49164
C
411 | _ -> k e in
412
fc1ad971
C
413 let case_line r k e =
414 mcodekind (Ast0.get_mcodekind e) &&
415 match Ast0.unwrap e with
416 Ast0.DisjCase(starter,case_list,mids,ender) ->
417 List.for_all r.VT0.combiner_rec_case_line case_list
418 | _ -> k e in
419
b1b2de81 420 V0.flat_combiner bind option_default
34e49164 421 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164 422 dots dots dots dots dots dots
d3f655c6 423 identifier expression typeC donothing donothing declaration
fc1ad971 424 statement case_line donothing
34e49164
C
425
426
427(* needs a special case when there is a Disj or an empty DOTS *)
428(* ---------------------------------------------------------------------- *)
429
430(*
431Doesn't really work:
432
433 if (acpi_device_dir(device))
434+ {
435 remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
436+ acpi_device_dir(device) = NULL;
437+ }
438
439The last two + lines get associated with the end of the if, not with the
440branch, so the braces get added in oddly.
441*)
442
443let add_braces orig_s =
b1b2de81
C
444 let s =
445 (Iso_pattern.rebuild_mcode None).VT0.rebuilder_rec_statement orig_s in
34e49164
C
446 let new_mcodekind =
447 match Ast0.get_mcodekind s with
448 Ast0.MINUS(mc) ->
449 let (text,tinfo) = !mc in
8babbc8f
C
450 let inner_text =
451 match text with
452 Ast.NOREPLACEMENT -> [[Ast.mkToken "{}"]]
453 | Ast.REPLACEMENT(anythings,Ast.ONE) ->
454 [Ast.mkToken "{"]::anythings@[[Ast.mkToken "}"]]
455 | Ast.REPLACEMENT(anythings,Ast.MANY) ->
456 failwith "++ not supported when braces must be added" in
457 Ast0.MINUS(ref(Ast.REPLACEMENT(inner_text,Ast.ONE),tinfo))
34e49164
C
458 | Ast0.CONTEXT(mc) ->
459 let (text,tinfo1,tinfo2) = !mc in
460 let new_text =
951c7801
C
461 (* this is going to be a mess if we allow it to be iterable...
462 there would be one level of braces for every added things.
463 need to come up with something better, or just add {} in the
464 source code. *)
34e49164 465 match text with
951c7801
C
466 Ast.BEFORE(bef,_) ->
467 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]],
468 Ast.ONE)
469 | Ast.AFTER(aft,_) ->
470 Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]],
471 Ast.ONE)
472 | Ast.BEFOREAFTER(bef,aft,_) ->
473 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]],
474 Ast.ONE)
34e49164 475 | Ast.NOTHING ->
951c7801
C
476 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]],
477 Ast.ONE) in
34e49164
C
478 Ast0.CONTEXT(ref(new_text,tinfo1,tinfo2))
479 | Ast0.MIXED(mc) ->
480 let (text,tinfo1,tinfo2) = !mc in
481 let new_text =
482 match text with
951c7801
C
483 Ast.BEFORE(bef,_) ->
484 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]],
485 Ast.ONE)
486 | Ast.AFTER(aft,_) ->
487 Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]],
488 Ast.ONE)
489 | Ast.BEFOREAFTER(bef,aft,_) ->
490 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]],
491 Ast.ONE)
34e49164 492 | Ast.NOTHING ->
951c7801
C
493 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]],
494 Ast.ONE) in
34e49164
C
495 Ast0.MIXED(ref(new_text,tinfo1,tinfo2))
496 | _ -> failwith "unexpected plus code" in
497 Ast0.set_mcodekind s new_mcodekind;
978fd7e5 498 Compute_lines.compute_statement_lines true s
34e49164
C
499
500(* ---------------------------------------------------------------------- *)
501
502let is_dots x =
503 match Ast0.unwrap x with
504 Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_)
505 | Ast0.Nest(_,_,_,_,_) -> true
506 | _ -> false
507
508let all_minus s =
509 match Ast0.get_mcodekind s with
510 Ast0.MINUS(_) -> true
511 | _ -> false
512
513let rec unchanged_minus s =
514 match Ast0.get_mcodekind s with
8babbc8f
C
515 Ast0.MINUS(mc) ->
516 (match !mc with (Ast.NOREPLACEMENT,_) -> true | _ -> false)
34e49164
C
517 | _ -> false
518
519let rec do_branch s =
520 if unchanged_minus s
521 then
522 Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(add_braces s))
523 else
524 match Ast0.unwrap s with
525 Ast0.Disj(starter,statement_dots_list,mids,ender) ->
526 let stmts =
527 List.map
528 (function s ->
529 match Ast0.unwrap s with
530 Ast0.DOTS([s]) ->
531 Ast0.rewrap s (Ast0.DOTS([do_branch s]))
532 | Ast0.DOTS(_) -> s
533 | _ -> failwith "not supported")
534 statement_dots_list in
535 Ast0.rewrap s (Ast0.Disj(starter,stmts,mids,ender))
536 | _ -> s
537
538let rec statement dots_before dots_after s =
539 let do_one s =
540 if dots_before && dots_after
541 then
542 if unchanged_minus s
543 then
544 (let with_braces = add_braces s in
545 Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(with_braces)))
546 else if adding_something s
547 then
548 (let with_braces = add_braces s in
549 Ast0.set_dots_bef_aft s (Ast0.AddingBetweenDots(with_braces)))
550 else s
551 else s in
552
553 match Ast0.unwrap s with
554 Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
555 (* true for close brace, because that represents any way we can
556 exit the function, which is not necessarily followed by an explicit
557 close brace. *)
558 Ast0.rewrap s
559 (Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace,
560 statement_dots false true body,
561 rbrace))
562 | Ast0.Decl(_,_) -> s
563 | Ast0.Seq(lbrace,body,rbrace) ->
564 Ast0.rewrap s
565 (Ast0.Seq(lbrace,statement_dots false false body,rbrace))
566 | Ast0.ExprStatement(exp,sem) -> do_one s
567 | Ast0.IfThen(iff,lp,exp,rp,branch1,x) ->
568 do_one
569 (Ast0.rewrap s
570 (Ast0.IfThen(iff,lp,exp,rp,statement false false branch1,x)))
571 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,x) ->
572 do_one
573 (Ast0.rewrap s
574 (Ast0.IfThenElse
575 (iff,lp,exp,rp,
576 statement false false branch1,els,
577 statement false false branch2,x)))
578 | Ast0.While(whl,lp,exp,rp,body,x) ->
579 do_one
580 (Ast0.rewrap s
581 (Ast0.While(whl,lp,exp,rp,statement false false body,x)))
582 | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
583 do_one
584 (Ast0.rewrap s
585 (Ast0.Do(d,statement false false body,whl,lp,exp,rp,sem)))
586 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,x) ->
587 do_one
588 (Ast0.rewrap s
589 (Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,
590 statement false false body,x)))
591 | Ast0.Iterator(nm,lp,args,rp,body,x) ->
592 do_one
593 (Ast0.rewrap s
594 (Ast0.Iterator(nm,lp,args,rp,statement false false body,x)))
fc1ad971 595 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
34e49164
C
596 do_one
597 (Ast0.rewrap s
fc1ad971 598 (Ast0.Switch(switch,lp,exp,rp,lb,decls,
34e49164 599 Ast0.rewrap cases
fc1ad971
C
600 (Ast0.DOTS
601 (List.map case_line (Ast0.undots cases))),
34e49164
C
602 rb)))
603 | Ast0.Break(br,sem) -> do_one s
604 | Ast0.Continue(cont,sem) -> do_one s
605 | Ast0.Label(l,dd) -> do_one s
606 | Ast0.Goto(goto,l,sem) -> do_one s
607 | Ast0.Return(ret,sem) -> do_one s
608 | Ast0.ReturnExpr(ret,exp,sem) -> do_one s
609 | Ast0.MetaStmt(name,_) -> do_one s
610 | Ast0.MetaStmtList(name,_) -> do_one s
611 | Ast0.Disj(starter,statement_dots_list,mids,ender) ->
612 Ast0.rewrap s
613 (Ast0.Disj(starter,
614 List.map (statement_dots dots_before dots_after)
615 statement_dots_list,
616 mids,ender))
617 | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
5636bb2c
C
618 (match Ast0.get_mcode_mcodekind starter with
619 Ast0.MINUS _ -> (* everything removed, like -... *) s
620 | _ ->
621 Ast0.rewrap s
622 (Ast0.Nest
623 (starter,statement_dots true true stmt_dots,ender,
624 whencode,multi)))
34e49164
C
625 | Ast0.Exp(exp) -> s
626 | Ast0.TopExp(exp) -> s
627 | Ast0.Ty(ty) -> s
1be43e12 628 | Ast0.TopInit(init) -> s
34e49164
C
629 | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> s
630 | Ast0.Include(inc,string) -> s (* doesn't affect the need for braces *)
3a314143 631 | Ast0.Undef(def,id) -> s (* same as include *)
34e49164 632 | Ast0.Define(def,id,params,body) -> s (* same as include *)
faf9a90c 633 | Ast0.OptStm(re) ->
34e49164
C
634 Ast0.rewrap s
635 (Ast0.OptStm(statement dots_before dots_after re))
636 | Ast0.UniqueStm(re) ->
637 Ast0.rewrap s
638 (Ast0.UniqueStm(statement dots_before dots_after re))
17ba0788 639 | Ast0.AsStmt _ -> failwith "not possible"
34e49164
C
640
641and case_line c =
642 Ast0.rewrap c
643 (match Ast0.unwrap c with
644 Ast0.Default(def,colon,code) ->
645 Ast0.Default(def,colon,statement_dots false false code)
646 | Ast0.Case(case,exp,colon,code) ->
647 Ast0.Case(case,exp,colon,statement_dots false false code)
fc1ad971
C
648 | Ast0.DisjCase(starter,case_lines,mids,ender) ->
649 Ast0.DisjCase(starter,List.map case_line case_lines,mids,ender)
34e49164 650 | Ast0.OptCase(case) -> Ast0.OptCase(case_line c))
faf9a90c 651
34e49164
C
652and do_statement_dots dots_before dots_after = function
653 [] -> []
654 | [x] -> [statement dots_before dots_after x]
655 | dots::rest when is_dots dots ->
656 dots::(do_statement_dots true dots_after rest)
657 | x::(dots::_ as rest) when is_dots dots ->
658 (statement dots_before true x)::
659 do_statement_dots false dots_after rest
660 | x::rest ->
661 (statement dots_before false x)::
662 do_statement_dots false dots_after rest
faf9a90c 663
34e49164
C
664and statement_dots dots_before dots_after d =
665 Ast0.rewrap d
666 (match Ast0.unwrap d with
667 Ast0.DOTS(l) ->
668 Ast0.DOTS(do_statement_dots dots_before dots_after l)
669 | Ast0.CIRCLES(l) ->
670 Ast0.CIRCLES(do_statement_dots dots_before dots_after l)
671 | Ast0.STARS(l) ->
672 Ast0.STARS(do_statement_dots dots_before dots_after l))
673
674let top_level t =
675 Ast0.rewrap t
676 (match Ast0.unwrap t with
65038c61 677 Ast0.NONDECL(stmt_dots) -> Ast0.NONDECL(statement true true stmt_dots)
34e49164
C
678 | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots true true stmt_dots)
679 | t -> t)
680
681let single_statement l =
682 if !Flag_parsing_cocci.sgrep_mode then l else List.map top_level l