Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / parsing_cocci / single_statement.ml
1 (* detect statements that are between dots in the minus code, because they
2 may need a special treatment if they are if branches *)
3
4 module Ast0 = Ast0_cocci
5 module Ast = Ast_cocci
6 module V0 = Visitor_ast0
7 module VT0 = Visitor_ast0_types
8
9 (* --------------------------------------------------------------------- *)
10 (* --------------------------------------------------------------------- *)
11 (* Helpers *)
12
13 let left_dots f l =
14 match Ast0.undots l with
15 [] -> false
16 | x::xs -> f x
17
18 let right_dots f l =
19 match List.rev (Ast0.undots l) with
20 [] -> false
21 | x::xs -> f x
22
23 let 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*)
26 | Ast0.PLUS _ -> failwith "not possible"
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
34 let modif_after_mcodekind = function
35 Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
36 | Ast0.PLUS _ -> failwith "not possible"
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
44 let modif_after_mcode mc = modif_after_mcodekind (Ast0.get_mcode_mcodekind mc)
45
46 let any_statements =
47 List.exists
48 (List.exists
49 (function
50 Ast.StatementTag(_) | Ast.StmtDotsTag(_)
51 | Ast.DeclarationTag(_) | Ast.DeclDotsTag(_) -> true | _ -> false))
52
53 let modif_before x =
54 match Ast0.get_mcodekind x with
55 Ast0.PLUS _ -> failwith "not possible"
56 | Ast0.MINUS mc ->
57 (match !mc with
58 (* do better for the common case of replacing a stmt by another one *)
59 ([[Ast.StatementTag(s)]],ti) ->
60 (match Ast.unwrap s with
61 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
62 | _ -> mc := ([[Ast.StatementTag(s)]],ti); false)
63 | (_,_) -> true)
64 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
65 (match !mc with
66 (Ast.BEFORE _,_,_) -> true
67 | (Ast.BEFOREAFTER _,_,_) -> true
68 | _ -> false)
69
70 let modif_after x =
71 match Ast0.get_mcodekind x with
72 Ast0.PLUS _ -> failwith "not possible"
73 | Ast0.MINUS mc ->
74 (match !mc with
75 (* do better for the common case of replacing a stmt by another one *)
76 ([[Ast.StatementTag(s)]],ti) ->
77 (match Ast.unwrap s with
78 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
79 | _ -> mc := ([[Ast.StatementTag(s)]],ti); false)
80 | (l,_) when any_statements l -> true
81 | (l,ti) -> mc := (l,ti); false)
82 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
83 (match !mc with
84 (Ast.AFTER _,_,_) -> true
85 | (Ast.BEFOREAFTER _,_,_) -> true
86 | _ -> false)
87
88 (* Identifier *)
89 let 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
102 let 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
137 and left_typeC t =
138 modif_before t or
139 match Ast0.unwrap t with
140 Ast0.ConstVol(cv,ty) -> modif_before_mcode cv
141 | Ast0.BaseType(ty,strings) -> modif_before_mcode (List.hd strings)
142 | Ast0.Signed(sgn,ty) -> modif_before_mcode sgn
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
148 | Ast0.EnumName(kind,name) -> modif_before_mcode kind
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
162 and 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
177 and 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
193 and 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
209 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
210 modif_before_mcode switch
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 *)
226 | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
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
233 and 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
250 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) -> modif_after_mcode rb
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 *)
266 | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
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
277 if a new statement is added. For this it would be best to correlate with the
278 plus slice. Or at least be sure that the new stuff is on the far left or
279 far right. *)
280
281 let 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 *)
286 ([[Ast.StatementTag(s)]],ti) ->
287 (match Ast.unwrap s with
288 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
289 | _ -> mc := ([[Ast.StatementTag(s)]],ti); false)
290 | (_,_) -> true)
291 | Ast0.CONTEXT(mc) ->
292 let (text,tinfo1,tinfo2) = !mc in
293 (match text with Ast.NOTHING -> false | _ -> true)
294 | Ast0.MIXED(_) ->
295 not(contains_only_minus.VT0.combiner_rec_statement s) (*&&
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 *)
300 and 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
310 let mcode (_,_,_,mc,_,_) = mcodekind mc in
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) ->
323 List.for_all r.VT0.combiner_rec_expression expr_list
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) ->
330 List.for_all r.VT0.combiner_rec_declaration decls
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) ->
337 List.for_all r.VT0.combiner_rec_typeC types
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) ->
344 List.for_all r.VT0.combiner_rec_statement_dots statement_dots_list
345 | _ -> k e in
346
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
354 V0.flat_combiner bind option_default
355 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
356 dots dots dots dots dots dots
357 donothing expression typeC donothing donothing declaration
358 statement case_line donothing
359
360
361 (* needs a special case when there is a Disj or an empty DOTS *)
362 (* ---------------------------------------------------------------------- *)
363
364 (*
365 Doesn'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
373 The last two + lines get associated with the end of the if, not with the
374 branch, so the braces get added in oddly.
375 *)
376
377 let add_braces orig_s =
378 let s =
379 (Iso_pattern.rebuild_mcode None).VT0.rebuilder_rec_statement orig_s in
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 =
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. *)
392 match text with
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)
402 | Ast.NOTHING ->
403 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]],
404 Ast.ONE) in
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
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)
419 | Ast.NOTHING ->
420 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]],
421 Ast.ONE) in
422 Ast0.MIXED(ref(new_text,tinfo1,tinfo2))
423 | _ -> failwith "unexpected plus code" in
424 Ast0.set_mcodekind s new_mcodekind;
425 Compute_lines.compute_statement_lines true s
426
427 (* ---------------------------------------------------------------------- *)
428
429 let is_dots x =
430 match Ast0.unwrap x with
431 Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_)
432 | Ast0.Nest(_,_,_,_,_) -> true
433 | _ -> false
434
435 let all_minus s =
436 match Ast0.get_mcodekind s with
437 Ast0.MINUS(_) -> true
438 | _ -> false
439
440 let rec unchanged_minus s =
441 match Ast0.get_mcodekind s with
442 Ast0.MINUS(mc) -> (match !mc with ([],_) -> true | _ -> false)
443 | _ -> false
444
445 let 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
464 let 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)))
521 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
522 do_one
523 (Ast0.rewrap s
524 (Ast0.Switch(switch,lp,exp,rp,lb,decls,
525 Ast0.rewrap cases
526 (Ast0.DOTS
527 (List.map case_line (Ast0.undots cases))),
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
550 | Ast0.TopInit(init) -> s
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 *)
554 | Ast0.OptStm(re) ->
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
561 and 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)
568 | Ast0.DisjCase(starter,case_lines,mids,ender) ->
569 Ast0.DisjCase(starter,List.map case_line case_lines,mids,ender)
570 | Ast0.OptCase(case) -> Ast0.OptCase(case_line c))
571
572 and 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
583
584 and 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
594 let 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
601 let single_statement l =
602 if !Flag_parsing_cocci.sgrep_mode then l else List.map top_level l