Release coccinelle-0.1.1
[bpt/coccinelle.git] / parsing_cocci / single_statement.ml
CommitLineData
34e49164
C
1(*
2* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
3* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
4* This file is part of Coccinelle.
5*
6* Coccinelle is free software: you can redistribute it and/or modify
7* it under the terms of the GNU General Public License as published by
8* the Free Software Foundation, according to version 2 of the License.
9*
10* Coccinelle is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17*
18* The authors reserve the right to distribute this or future versions of
19* Coccinelle under other licenses.
20*)
21
22
23(* detect statements that are between dots in the minus code, because they
24may need a special treatment if they are if branches *)
25
26module Ast0 = Ast0_cocci
27module Ast = Ast_cocci
28module V0 = Visitor_ast0
29
30(* --------------------------------------------------------------------- *)
31(* --------------------------------------------------------------------- *)
32(* Helpers *)
33
34let left_dots f l =
35 match Ast0.undots l with
36 [] -> false
37 | x::xs -> f x
38
39let right_dots f l =
40 match List.rev (Ast0.undots l) with
41 [] -> false
42 | x::xs -> f x
43
44let modif_before_mcode mc =
45 match Ast0.get_mcode_mcodekind mc with
46 Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
47 | Ast0.PLUS -> failwith "not possible"
48 | Ast0.CONTEXT mc ->
49 (match !mc with
50 (Ast.BEFORE _,_,_) -> true
51 | (Ast.BEFOREAFTER _,_,_) -> true
52 | _ -> false)
53 | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
54
55let modif_after_mcodekind = function
56 Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
57 | Ast0.PLUS -> failwith "not possible"
58 | Ast0.CONTEXT mc ->
59 (match !mc with
60 (Ast.AFTER _,_,_) -> true
61 | (Ast.BEFOREAFTER _,_,_) -> true
62 | _ -> false)
63 | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
64
65let modif_after_mcode mc = modif_after_mcodekind (Ast0.get_mcode_mcodekind mc)
66
67let any_statements =
68 List.exists
69 (List.exists
70 (function
71 Ast.StatementTag(_) | Ast.StmtDotsTag(_)
72 | Ast.DeclarationTag(_) | Ast.DeclDotsTag(_) -> true | _ -> false))
73
74let modif_before x =
75 match Ast0.get_mcodekind x with
76 Ast0.PLUS -> failwith "not possible"
77 | Ast0.MINUS mc ->
78 (match !mc with
79 (* do better for the common case of replacing a stmt by another one *)
80 ([[Ast.StatementTag(s)]],_) ->
81 (match Ast.unwrap s with
82 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
83 | _ -> false)
84 | (_,_) -> true)
85 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
86 (match !mc with
87 (Ast.BEFORE _,_,_) -> true
88 | (Ast.BEFOREAFTER _,_,_) -> true
89 | _ -> false)
90
91let modif_after x =
92 match Ast0.get_mcodekind x with
93 Ast0.PLUS -> failwith "not possible"
94 | Ast0.MINUS mc ->
95 (match !mc with
96 (* do better for the common case of replacing a stmt by another one *)
97 ([[Ast.StatementTag(s)]],_) ->
98 (match Ast.unwrap s with
99 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
100 | _ -> false)
101 | (l,_) -> any_statements l)
102 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
103 (match !mc with
104 (Ast.AFTER _,_,_) -> true
105 | (Ast.BEFOREAFTER _,_,_) -> true
106 | _ -> false)
107
108(* Identifier *)
109let rec left_ident i =
110 modif_before i or
111 match Ast0.unwrap i with
112 Ast0.Id(name) -> modif_before_mcode name
113 | Ast0.MetaId(name,_,_) -> modif_before_mcode name
114 | Ast0.MetaFunc(name,_,_) -> modif_before_mcode name
115 | Ast0.MetaLocalFunc(name,_,_) -> modif_before_mcode name
116 | Ast0.OptIdent(id) -> left_ident id
117 | Ast0.UniqueIdent(id) -> left_ident id
118
119(* --------------------------------------------------------------------- *)
120(* Expression *)
121
122let rec left_expression e =
123 modif_before e or
124 match Ast0.unwrap e with
125 Ast0.Ident(id) -> left_ident id
126 | Ast0.Constant(const) -> modif_before_mcode const
127 | Ast0.FunCall(fn,lp,args,rp) -> left_expression fn
128 | Ast0.Assignment(left,op,right,_) -> left_expression left
129 | Ast0.CondExpr(exp1,why,exp2,colon,exp3) -> left_expression exp1
130 | Ast0.Postfix(exp,op) -> left_expression exp
131 | Ast0.Infix(exp,op) -> modif_before_mcode op
132 | Ast0.Unary(exp,op) -> modif_before_mcode op
133 | Ast0.Binary(left,op,right) -> left_expression left
134 | Ast0.Nested(left,op,right) -> left_expression left
135 | Ast0.Paren(lp,exp,rp) -> modif_before_mcode lp
136 | Ast0.ArrayAccess(exp1,lb,exp2,rb) -> left_expression exp1
137 | Ast0.RecordAccess(exp,pt,field) -> left_expression exp
138 | Ast0.RecordPtAccess(exp,ar,field) -> left_expression exp
139 | Ast0.Cast(lp,ty,rp,exp) -> modif_before_mcode lp
140 | Ast0.SizeOfExpr(szf,exp) -> modif_before_mcode szf
141 | Ast0.SizeOfType(szf,lp,ty,rp) -> modif_before_mcode szf
142 | Ast0.TypeExp(ty) -> left_typeC ty
143 | Ast0.MetaErr(name,_,_) -> modif_before_mcode name
144 | Ast0.MetaExpr(name,_,ty,_,_) -> modif_before_mcode name
145 | Ast0.MetaExprList(name,_,_) -> modif_before_mcode name
146 | Ast0.EComma(cm) -> modif_before_mcode cm
147 | Ast0.DisjExpr(_,exp_list,_,_) -> List.exists left_expression exp_list
148 | Ast0.NestExpr(starter,expr_dots,ender,_,multi) ->
149 left_dots left_expression expr_dots
150 | Ast0.Edots(dots,_) | Ast0.Ecircles(dots,_) | Ast0.Estars(dots,_) -> false
151 | Ast0.OptExp(exp) -> left_expression exp
152 | Ast0.UniqueExp(exp) -> left_expression exp
153
154(* --------------------------------------------------------------------- *)
155(* Types *)
156
157and left_typeC t =
158 modif_before t or
159 match Ast0.unwrap t with
160 Ast0.ConstVol(cv,ty) -> modif_before_mcode cv
161 | Ast0.BaseType(ty,Some sgn) -> modif_before_mcode sgn
162 | Ast0.BaseType(ty,None) -> modif_before_mcode ty
163 | Ast0.ImplicitInt(sgn) -> modif_before_mcode sgn
164 | Ast0.Pointer(ty,star) -> left_typeC ty
165 | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> left_typeC ty
166 | Ast0.FunctionType(Some ty,lp1,params,rp1) -> left_typeC ty
167 | Ast0.FunctionType(None,lp1,params,rp1) -> modif_before_mcode lp1
168 | Ast0.Array(ty,lb,size,rb) -> left_typeC ty
169 | Ast0.StructUnionName(kind,name) -> modif_before_mcode kind
170 | Ast0.StructUnionDef(ty,lb,decls,rb) -> left_typeC ty
171 | Ast0.TypeName(name) -> modif_before_mcode name
172 | Ast0.MetaType(name,_) -> modif_before_mcode name
173 | Ast0.DisjType(lp,types,mids,rp) -> List.exists left_typeC types
174 | Ast0.OptType(ty) -> left_typeC ty
175 | Ast0.UniqueType(ty) -> left_typeC ty
176
177(* --------------------------------------------------------------------- *)
178(* Variable declaration *)
179(* Even if the Cocci program specifies a list of declarations, they are
180 split out into multiple declarations of a single variable each. *)
181
182and left_declaration d =
183 modif_before d or
184 match Ast0.unwrap d with
185 Ast0.Init(Some stg,ty,id,eq,ini,sem) -> modif_before_mcode stg
186 | Ast0.Init(None,ty,id,eq,ini,sem) -> left_typeC ty
187 | Ast0.UnInit(Some stg,ty,id,sem) -> modif_before_mcode stg
188 | Ast0.UnInit(None,ty,id,sem) -> left_typeC ty
189 | Ast0.MacroDecl(name,lp,args,rp,sem) -> left_ident name
190 | Ast0.TyDecl(ty,sem) -> left_typeC ty
191 | Ast0.Typedef(stg,ty,id,sem) -> modif_before_mcode stg
192 | Ast0.DisjDecl(_,decls,_,_) -> List.exists left_declaration decls
193 | Ast0.Ddots(dots,_) -> false
194 | Ast0.OptDecl(decl) -> left_declaration decl
195 | Ast0.UniqueDecl(decl) -> left_declaration decl
196
197and right_declaration d =
198 modif_before d or
199 match Ast0.unwrap d with
200 Ast0.Init(_,ty,id,eq,ini,sem) -> modif_after_mcode sem
201 | Ast0.UnInit(_,ty,id,sem) -> modif_after_mcode sem
202 | Ast0.MacroDecl(name,lp,args,rp,sem) -> modif_after_mcode sem
203 | Ast0.TyDecl(ty,sem) -> modif_after_mcode sem
204 | Ast0.Typedef(stg,ty,id,sem) -> modif_after_mcode sem
205 | Ast0.DisjDecl(_,decls,_,_) -> List.exists right_declaration decls
206 | Ast0.Ddots(dots,_) -> false
207 | Ast0.OptDecl(decl) -> right_declaration decl
208 | Ast0.UniqueDecl(decl) -> right_declaration decl
209
210(* --------------------------------------------------------------------- *)
211(* Top-level code *)
212
213and left_statement s =
214 modif_before s or
215 match Ast0.unwrap s with
216 Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
217 (* irrelevant *) false
218 | Ast0.Decl(_,decl) -> left_declaration decl
219 | Ast0.Seq(lbrace,body,rbrace) -> modif_before_mcode lbrace
220 | Ast0.ExprStatement(exp,sem) -> left_expression exp
221 | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_before_mcode iff
222 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
223 modif_before_mcode iff
224 | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_before_mcode whl
225 | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_before_mcode d
226 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
227 modif_before_mcode fr
228 | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) -> left_ident nm
229 | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) -> modif_before_mcode switch
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
248 | Ast0.Define(def,id,params,body) -> modif_before_mcode def
249 | Ast0.OptStm(re) -> left_statement re
250 | Ast0.UniqueStm(re) -> left_statement re
251
252and right_statement s =
253 modif_after s or
254 match Ast0.unwrap s with
255 Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
256 (* irrelevant *) false
257 | Ast0.Decl(_,decl) -> right_declaration decl
258 | Ast0.Seq(lbrace,body,rbrace) -> modif_after_mcode rbrace
259 | Ast0.ExprStatement(exp,sem) -> modif_after_mcode sem
260 | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_after_mcodekind aft
261 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
262 modif_after_mcodekind aft
263 | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_after_mcodekind aft
264 | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_after_mcode sem
265 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
266 modif_after_mcodekind aft
267 | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) ->
268 modif_after_mcodekind aft
269 | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) -> modif_after_mcode rb
270 | Ast0.Break(br,sem) -> modif_after_mcode sem
271 | Ast0.Continue(cont,sem) -> modif_after_mcode sem
272 | Ast0.Label(l,dd) -> modif_after_mcode dd
273 | Ast0.Goto(goto,l,sem) -> modif_after_mcode sem
274 | Ast0.Return(ret,sem) -> modif_after_mcode sem
275 | Ast0.ReturnExpr(ret,exp,sem) -> modif_after_mcode sem
276 | Ast0.MetaStmt(name,pure) -> modif_after_mcode name
277 | Ast0.MetaStmtList(name,_) -> modif_after_mcode name
278 | Ast0.Disj(_,statement_dots_list,_,_) ->
279 List.exists (right_dots right_statement) statement_dots_list
280 | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
281 right_dots right_statement stmt_dots
282 | Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
283 | Ast0.TopExp(exp) -> false (* as above *)
284 | Ast0.Ty(ty) -> false (* can only be replaced by a type *)
1be43e12 285 | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
34e49164
C
286 | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
287 | Ast0.Include(inc,s) -> modif_after_mcode s
288 | Ast0.Define(def,id,params,body) -> right_dots right_statement body
289 | Ast0.OptStm(re) -> right_statement re
290 | Ast0.UniqueStm(re) -> right_statement re
291
292(* --------------------------------------------------------------------- *)
293
294
295(* A very coarse approximation. We would really only like to return true
296if a new statement is added. For this it would be best to correlate with the
297plus slice. Or at least be sure that the new stuff is on the far left or
298far right. *)
299
300let rec adding_something s =
301 match Ast0.get_mcodekind s with
302 Ast0.MINUS(mc) ->
303 (match !mc with
304 (* do better for the common case of replacing a stmt by another one *)
305 ([[Ast.StatementTag(s)]],_) ->
306 (match Ast.unwrap s with
307 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
308 | _ -> false)
309 | (_,_) -> true)
310 | Ast0.CONTEXT(mc) ->
311 let (text,tinfo1,tinfo2) = !mc in
312 (match text with Ast.NOTHING -> false | _ -> true)
313 | Ast0.MIXED(_) ->
314 not(contains_only_minus.V0.combiner_statement s) (*&&
315 (left_statement s) or (right_statement s)*)
316 | _ -> failwith "unexpected plus code"
317
318(* why do we need this; MINUS should mean the same thing *)
319and contains_only_minus =
320 let bind x y = x && y in
321 let option_default = true in
322 let mcodekind = function
323 Ast0.MINUS(mc) ->
324 (match !mc with
325 ([],_) -> true
326 | _ -> false)
327 | Ast0.CONTEXT(mc) -> false
328 | _ -> false in
329 let mcode (_,_,_,mc,_) = mcodekind mc in
330
331 let donothing r k e = mcodekind (Ast0.get_mcodekind e) && k e in
332
333 let dots r k e =
334 match Ast0.unwrap e with
335 Ast0.DOTS([]) | Ast0.CIRCLES([]) | Ast0.STARS([]) -> true
336 | _ -> k e in
337
338 let expression r k e =
339 mcodekind (Ast0.get_mcodekind e) &&
340 match Ast0.unwrap e with
341 Ast0.DisjExpr(starter,expr_list,mids,ender) ->
342 List.for_all r.V0.combiner_expression expr_list
343 | _ -> k e in
344
345 let declaration r k e =
346 mcodekind (Ast0.get_mcodekind e) &&
347 match Ast0.unwrap e with
348 Ast0.DisjDecl(starter,decls,mids,ender) ->
349 List.for_all r.V0.combiner_declaration decls
350 | _ -> k e in
351
352 let typeC r k e =
353 mcodekind (Ast0.get_mcodekind e) &&
354 match Ast0.unwrap e with
355 Ast0.DisjType(starter,types,mids,ender) ->
356 List.for_all r.V0.combiner_typeC types
357 | _ -> k e in
358
359 let statement r k e =
360 mcodekind (Ast0.get_mcodekind e) &&
361 match Ast0.unwrap e with
362 Ast0.Disj(starter,statement_dots_list,mids,ender) ->
363 List.for_all r.V0.combiner_statement_dots statement_dots_list
364 | _ -> k e in
365
366 V0.combiner bind option_default
367 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
368 mcode
369 dots dots dots dots dots dots
370 donothing expression typeC donothing donothing declaration
371 statement donothing donothing
372
373
374(* needs a special case when there is a Disj or an empty DOTS *)
375(* ---------------------------------------------------------------------- *)
376
377(*
378Doesn't really work:
379
380 if (acpi_device_dir(device))
381+ {
382 remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
383+ acpi_device_dir(device) = NULL;
384+ }
385
386The last two + lines get associated with the end of the if, not with the
387branch, so the braces get added in oddly.
388*)
389
390let add_braces orig_s =
391 let s = (Iso_pattern.rebuild_mcode None).V0.rebuilder_statement orig_s in
392 let new_mcodekind =
393 match Ast0.get_mcodekind s with
394 Ast0.MINUS(mc) ->
395 let (text,tinfo) = !mc in
396 Ast0.MINUS(ref([Ast.mkToken "{"]::text@[[Ast.mkToken "}"]],tinfo))
397 | Ast0.CONTEXT(mc) ->
398 let (text,tinfo1,tinfo2) = !mc in
399 let new_text =
400 match text with
401 Ast.BEFORE(bef) ->
402 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]])
403 | Ast.AFTER(aft) ->
404 Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]])
405 | Ast.BEFOREAFTER(bef,aft) ->
406 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]])
407 | Ast.NOTHING ->
408 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) in
409 Ast0.CONTEXT(ref(new_text,tinfo1,tinfo2))
410 | Ast0.MIXED(mc) ->
411 let (text,tinfo1,tinfo2) = !mc in
412 let new_text =
413 match text with
414 Ast.BEFORE(bef) ->
415 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]])
416 | Ast.AFTER(aft) ->
417 Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]])
418 | Ast.BEFOREAFTER(bef,aft) ->
419 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]])
420 | Ast.NOTHING ->
421 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) 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.statement s
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)))
521 | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
522 do_one
523 (Ast0.rewrap s
524 (Ast0.Switch(switch,lp,exp,rp,lb,
525 Ast0.rewrap cases
526 (Ast0.DOTS(List.map case_line (Ast0.undots cases))),
527 rb)))
528 | Ast0.Break(br,sem) -> do_one s
529 | Ast0.Continue(cont,sem) -> do_one s
530 | Ast0.Label(l,dd) -> do_one s
531 | Ast0.Goto(goto,l,sem) -> do_one s
532 | Ast0.Return(ret,sem) -> do_one s
533 | Ast0.ReturnExpr(ret,exp,sem) -> do_one s
534 | Ast0.MetaStmt(name,_) -> do_one s
535 | Ast0.MetaStmtList(name,_) -> do_one s
536 | Ast0.Disj(starter,statement_dots_list,mids,ender) ->
537 Ast0.rewrap s
538 (Ast0.Disj(starter,
539 List.map (statement_dots dots_before dots_after)
540 statement_dots_list,
541 mids,ender))
542 | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
543 Ast0.rewrap s
544 (Ast0.Nest
545 (starter,statement_dots true true stmt_dots,ender,whencode,multi))
546 | Ast0.Exp(exp) -> s
547 | Ast0.TopExp(exp) -> s
548 | Ast0.Ty(ty) -> s
1be43e12 549 | Ast0.TopInit(init) -> s
34e49164
C
550 | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> s
551 | Ast0.Include(inc,string) -> s (* doesn't affect the need for braces *)
552 | Ast0.Define(def,id,params,body) -> s (* same as include *)
553 | Ast0.OptStm(re) ->
554 Ast0.rewrap s
555 (Ast0.OptStm(statement dots_before dots_after re))
556 | Ast0.UniqueStm(re) ->
557 Ast0.rewrap s
558 (Ast0.UniqueStm(statement dots_before dots_after re))
559
560and case_line c =
561 Ast0.rewrap c
562 (match Ast0.unwrap c with
563 Ast0.Default(def,colon,code) ->
564 Ast0.Default(def,colon,statement_dots false false code)
565 | Ast0.Case(case,exp,colon,code) ->
566 Ast0.Case(case,exp,colon,statement_dots false false code)
567 | Ast0.OptCase(case) -> Ast0.OptCase(case_line c))
568
569and do_statement_dots dots_before dots_after = function
570 [] -> []
571 | [x] -> [statement dots_before dots_after x]
572 | dots::rest when is_dots dots ->
573 dots::(do_statement_dots true dots_after rest)
574 | x::(dots::_ as rest) when is_dots dots ->
575 (statement dots_before true x)::
576 do_statement_dots false dots_after rest
577 | x::rest ->
578 (statement dots_before false x)::
579 do_statement_dots false dots_after rest
580
581and statement_dots dots_before dots_after d =
582 Ast0.rewrap d
583 (match Ast0.unwrap d with
584 Ast0.DOTS(l) ->
585 Ast0.DOTS(do_statement_dots dots_before dots_after l)
586 | Ast0.CIRCLES(l) ->
587 Ast0.CIRCLES(do_statement_dots dots_before dots_after l)
588 | Ast0.STARS(l) ->
589 Ast0.STARS(do_statement_dots dots_before dots_after l))
590
591let top_level t =
592 Ast0.rewrap t
593 (match Ast0.unwrap t with
594 Ast0.DECL(stmt_dots) -> Ast0.DECL(statement true true stmt_dots)
595 | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots true true stmt_dots)
596 | t -> t)
597
598let single_statement l =
599 if !Flag_parsing_cocci.sgrep_mode then l else List.map top_level l