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