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