Release coccinelle-0.1.8
[bpt/coccinelle.git] / parsing_cocci / single_statement.ml
CommitLineData
34e49164 1(*
faf9a90c 2* Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
34e49164
C
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
b1b2de81 29module VT0 = Visitor_ast0_types
34e49164
C
30
31(* --------------------------------------------------------------------- *)
32(* --------------------------------------------------------------------- *)
33(* Helpers *)
34
35let left_dots f l =
36 match Ast0.undots l with
37 [] -> false
38 | x::xs -> f x
39
40let right_dots f l =
41 match List.rev (Ast0.undots l) with
42 [] -> false
43 | x::xs -> f x
44
45let modif_before_mcode mc =
46 match Ast0.get_mcode_mcodekind mc with
47 Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
48 | Ast0.PLUS -> failwith "not possible"
49 | Ast0.CONTEXT mc ->
50 (match !mc with
51 (Ast.BEFORE _,_,_) -> true
52 | (Ast.BEFOREAFTER _,_,_) -> true
53 | _ -> false)
54 | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
55
56let modif_after_mcodekind = function
57 Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
58 | Ast0.PLUS -> failwith "not possible"
59 | Ast0.CONTEXT mc ->
60 (match !mc with
61 (Ast.AFTER _,_,_) -> true
62 | (Ast.BEFOREAFTER _,_,_) -> true
63 | _ -> false)
64 | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
65
66let modif_after_mcode mc = modif_after_mcodekind (Ast0.get_mcode_mcodekind mc)
67
68let any_statements =
69 List.exists
70 (List.exists
71 (function
72 Ast.StatementTag(_) | Ast.StmtDotsTag(_)
73 | Ast.DeclarationTag(_) | Ast.DeclDotsTag(_) -> true | _ -> false))
74
75let modif_before x =
76 match Ast0.get_mcodekind x with
77 Ast0.PLUS -> failwith "not possible"
78 | Ast0.MINUS mc ->
79 (match !mc with
80 (* do better for the common case of replacing a stmt by another one *)
81 ([[Ast.StatementTag(s)]],_) ->
82 (match Ast.unwrap s with
83 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
84 | _ -> false)
85 | (_,_) -> true)
86 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
87 (match !mc with
88 (Ast.BEFORE _,_,_) -> true
89 | (Ast.BEFOREAFTER _,_,_) -> true
90 | _ -> false)
91
92let modif_after x =
93 match Ast0.get_mcodekind x with
94 Ast0.PLUS -> failwith "not possible"
95 | Ast0.MINUS mc ->
96 (match !mc with
97 (* do better for the common case of replacing a stmt by another one *)
98 ([[Ast.StatementTag(s)]],_) ->
99 (match Ast.unwrap s with
100 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
101 | _ -> false)
102 | (l,_) -> any_statements l)
103 | Ast0.CONTEXT mc | Ast0.MIXED mc ->
104 (match !mc with
105 (Ast.AFTER _,_,_) -> true
106 | (Ast.BEFOREAFTER _,_,_) -> true
faf9a90c 107 | _ -> false)
34e49164
C
108
109(* Identifier *)
110let rec left_ident i =
111 modif_before i or
112 match Ast0.unwrap i with
113 Ast0.Id(name) -> modif_before_mcode name
114 | Ast0.MetaId(name,_,_) -> modif_before_mcode name
115 | Ast0.MetaFunc(name,_,_) -> modif_before_mcode name
116 | Ast0.MetaLocalFunc(name,_,_) -> modif_before_mcode name
117 | Ast0.OptIdent(id) -> left_ident id
118 | Ast0.UniqueIdent(id) -> left_ident id
119
120(* --------------------------------------------------------------------- *)
121(* Expression *)
122
123let rec left_expression e =
124 modif_before e or
125 match Ast0.unwrap e with
126 Ast0.Ident(id) -> left_ident id
127 | Ast0.Constant(const) -> modif_before_mcode const
128 | Ast0.FunCall(fn,lp,args,rp) -> left_expression fn
129 | Ast0.Assignment(left,op,right,_) -> left_expression left
130 | Ast0.CondExpr(exp1,why,exp2,colon,exp3) -> left_expression exp1
131 | Ast0.Postfix(exp,op) -> left_expression exp
132 | Ast0.Infix(exp,op) -> modif_before_mcode op
133 | Ast0.Unary(exp,op) -> modif_before_mcode op
134 | Ast0.Binary(left,op,right) -> left_expression left
135 | Ast0.Nested(left,op,right) -> left_expression left
136 | Ast0.Paren(lp,exp,rp) -> modif_before_mcode lp
137 | Ast0.ArrayAccess(exp1,lb,exp2,rb) -> left_expression exp1
138 | Ast0.RecordAccess(exp,pt,field) -> left_expression exp
139 | Ast0.RecordPtAccess(exp,ar,field) -> left_expression exp
140 | Ast0.Cast(lp,ty,rp,exp) -> modif_before_mcode lp
141 | Ast0.SizeOfExpr(szf,exp) -> modif_before_mcode szf
142 | Ast0.SizeOfType(szf,lp,ty,rp) -> modif_before_mcode szf
143 | Ast0.TypeExp(ty) -> left_typeC ty
144 | Ast0.MetaErr(name,_,_) -> modif_before_mcode name
145 | Ast0.MetaExpr(name,_,ty,_,_) -> modif_before_mcode name
146 | Ast0.MetaExprList(name,_,_) -> modif_before_mcode name
147 | Ast0.EComma(cm) -> modif_before_mcode cm
148 | Ast0.DisjExpr(_,exp_list,_,_) -> List.exists left_expression exp_list
149 | Ast0.NestExpr(starter,expr_dots,ender,_,multi) ->
150 left_dots left_expression expr_dots
151 | Ast0.Edots(dots,_) | Ast0.Ecircles(dots,_) | Ast0.Estars(dots,_) -> false
152 | Ast0.OptExp(exp) -> left_expression exp
153 | Ast0.UniqueExp(exp) -> left_expression exp
154
155(* --------------------------------------------------------------------- *)
156(* Types *)
157
158and left_typeC t =
159 modif_before t or
160 match Ast0.unwrap t with
161 Ast0.ConstVol(cv,ty) -> modif_before_mcode cv
faf9a90c
C
162 | Ast0.BaseType(ty,strings) -> modif_before_mcode (List.hd strings)
163 | Ast0.Signed(sgn,ty) -> modif_before_mcode sgn
34e49164
C
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
faf9a90c 169 | Ast0.EnumName(kind,name) -> modif_before_mcode kind
34e49164
C
170 | Ast0.StructUnionName(kind,name) -> modif_before_mcode kind
171 | Ast0.StructUnionDef(ty,lb,decls,rb) -> left_typeC ty
172 | Ast0.TypeName(name) -> modif_before_mcode name
173 | Ast0.MetaType(name,_) -> modif_before_mcode name
174 | Ast0.DisjType(lp,types,mids,rp) -> List.exists left_typeC types
175 | Ast0.OptType(ty) -> left_typeC ty
176 | Ast0.UniqueType(ty) -> left_typeC ty
177
178(* --------------------------------------------------------------------- *)
179(* Variable declaration *)
180(* Even if the Cocci program specifies a list of declarations, they are
181 split out into multiple declarations of a single variable each. *)
182
183and left_declaration d =
184 modif_before d or
185 match Ast0.unwrap d with
186 Ast0.Init(Some stg,ty,id,eq,ini,sem) -> modif_before_mcode stg
187 | Ast0.Init(None,ty,id,eq,ini,sem) -> left_typeC ty
188 | Ast0.UnInit(Some stg,ty,id,sem) -> modif_before_mcode stg
189 | Ast0.UnInit(None,ty,id,sem) -> left_typeC ty
190 | Ast0.MacroDecl(name,lp,args,rp,sem) -> left_ident name
191 | Ast0.TyDecl(ty,sem) -> left_typeC ty
192 | Ast0.Typedef(stg,ty,id,sem) -> modif_before_mcode stg
193 | Ast0.DisjDecl(_,decls,_,_) -> List.exists left_declaration decls
194 | Ast0.Ddots(dots,_) -> false
195 | Ast0.OptDecl(decl) -> left_declaration decl
196 | Ast0.UniqueDecl(decl) -> left_declaration decl
197
198and right_declaration d =
199 modif_before d or
200 match Ast0.unwrap d with
201 Ast0.Init(_,ty,id,eq,ini,sem) -> modif_after_mcode sem
202 | Ast0.UnInit(_,ty,id,sem) -> modif_after_mcode sem
203 | Ast0.MacroDecl(name,lp,args,rp,sem) -> modif_after_mcode sem
204 | Ast0.TyDecl(ty,sem) -> modif_after_mcode sem
205 | Ast0.Typedef(stg,ty,id,sem) -> modif_after_mcode sem
206 | Ast0.DisjDecl(_,decls,_,_) -> List.exists right_declaration decls
207 | Ast0.Ddots(dots,_) -> false
208 | Ast0.OptDecl(decl) -> right_declaration decl
209 | Ast0.UniqueDecl(decl) -> right_declaration decl
210
211(* --------------------------------------------------------------------- *)
212(* Top-level code *)
213
214and left_statement s =
215 modif_before s or
216 match Ast0.unwrap s with
217 Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
218 (* irrelevant *) false
219 | Ast0.Decl(_,decl) -> left_declaration decl
220 | Ast0.Seq(lbrace,body,rbrace) -> modif_before_mcode lbrace
221 | Ast0.ExprStatement(exp,sem) -> left_expression exp
222 | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_before_mcode iff
223 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
224 modif_before_mcode iff
225 | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_before_mcode whl
226 | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_before_mcode d
227 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
228 modif_before_mcode fr
229 | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) -> left_ident nm
230 | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) -> modif_before_mcode switch
231 | Ast0.Break(br,sem) -> modif_before_mcode br
232 | Ast0.Continue(cont,sem) -> modif_before_mcode cont
233 | Ast0.Label(l,dd) -> left_ident l
234 | Ast0.Goto(goto,l,sem) -> modif_before_mcode goto
235 | Ast0.Return(ret,sem) -> modif_before_mcode ret
236 | Ast0.ReturnExpr(ret,exp,sem) -> modif_before_mcode ret
237 | Ast0.MetaStmt(name,pure) -> modif_before_mcode name
238 | Ast0.MetaStmtList(name,_) -> modif_before_mcode name
239 | Ast0.Disj(_,statement_dots_list,_,_) ->
240 List.exists (left_dots left_statement) statement_dots_list
241 | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
242 left_dots left_statement stmt_dots
243 | Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
244 | Ast0.TopExp(exp) -> false (* as above *)
245 | Ast0.Ty(ty) -> false (* can only be replaced by a type *)
1be43e12 246 | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
34e49164
C
247 | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
248 | Ast0.Include(inc,s) -> modif_before_mcode inc
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
270 | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) -> modif_after_mcode rb
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
289 | Ast0.Define(def,id,params,body) -> right_dots right_statement body
290 | Ast0.OptStm(re) -> right_statement re
291 | Ast0.UniqueStm(re) -> right_statement re
292
293(* --------------------------------------------------------------------- *)
294
295
296(* A very coarse approximation. We would really only like to return true
297if a new statement is added. For this it would be best to correlate with the
298plus slice. Or at least be sure that the new stuff is on the far left or
299far right. *)
300
301let rec adding_something s =
302 match Ast0.get_mcodekind s with
303 Ast0.MINUS(mc) ->
304 (match !mc with
305 (* do better for the common case of replacing a stmt by another one *)
306 ([[Ast.StatementTag(s)]],_) ->
307 (match Ast.unwrap s with
308 Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
309 | _ -> false)
310 | (_,_) -> true)
311 | Ast0.CONTEXT(mc) ->
312 let (text,tinfo1,tinfo2) = !mc in
313 (match text with Ast.NOTHING -> false | _ -> true)
314 | Ast0.MIXED(_) ->
b1b2de81 315 not(contains_only_minus.VT0.combiner_rec_statement s) (*&&
34e49164
C
316 (left_statement s) or (right_statement s)*)
317 | _ -> failwith "unexpected plus code"
318
319(* why do we need this; MINUS should mean the same thing *)
320and contains_only_minus =
321 let bind x y = x && y in
322 let option_default = true in
323 let mcodekind = function
324 Ast0.MINUS(mc) ->
325 (match !mc with
326 ([],_) -> true
327 | _ -> false)
328 | Ast0.CONTEXT(mc) -> false
329 | _ -> false in
708f4980 330 let mcode (_,_,_,mc,_,_) = mcodekind mc in
34e49164
C
331
332 let donothing r k e = mcodekind (Ast0.get_mcodekind e) && k e in
333
334 let dots r k e =
335 match Ast0.unwrap e with
336 Ast0.DOTS([]) | Ast0.CIRCLES([]) | Ast0.STARS([]) -> true
337 | _ -> k e in
338
339 let expression r k e =
340 mcodekind (Ast0.get_mcodekind e) &&
341 match Ast0.unwrap e with
342 Ast0.DisjExpr(starter,expr_list,mids,ender) ->
b1b2de81 343 List.for_all r.VT0.combiner_rec_expression expr_list
34e49164
C
344 | _ -> k e in
345
346 let declaration r k e =
347 mcodekind (Ast0.get_mcodekind e) &&
348 match Ast0.unwrap e with
349 Ast0.DisjDecl(starter,decls,mids,ender) ->
b1b2de81 350 List.for_all r.VT0.combiner_rec_declaration decls
34e49164
C
351 | _ -> k e in
352
353 let typeC r k e =
354 mcodekind (Ast0.get_mcodekind e) &&
355 match Ast0.unwrap e with
356 Ast0.DisjType(starter,types,mids,ender) ->
b1b2de81 357 List.for_all r.VT0.combiner_rec_typeC types
34e49164
C
358 | _ -> k e in
359
360 let statement r k e =
361 mcodekind (Ast0.get_mcodekind e) &&
362 match Ast0.unwrap e with
363 Ast0.Disj(starter,statement_dots_list,mids,ender) ->
b1b2de81 364 List.for_all r.VT0.combiner_rec_statement_dots statement_dots_list
34e49164
C
365 | _ -> k e in
366
b1b2de81 367 V0.flat_combiner bind option_default
34e49164 368 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164
C
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 =
b1b2de81
C
391 let s =
392 (Iso_pattern.rebuild_mcode None).VT0.rebuilder_rec_statement orig_s in
34e49164
C
393 let new_mcodekind =
394 match Ast0.get_mcodekind s with
395 Ast0.MINUS(mc) ->
396 let (text,tinfo) = !mc in
397 Ast0.MINUS(ref([Ast.mkToken "{"]::text@[[Ast.mkToken "}"]],tinfo))
398 | Ast0.CONTEXT(mc) ->
399 let (text,tinfo1,tinfo2) = !mc in
400 let new_text =
401 match text with
402 Ast.BEFORE(bef) ->
403 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]])
404 | Ast.AFTER(aft) ->
405 Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]])
406 | Ast.BEFOREAFTER(bef,aft) ->
407 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]])
408 | Ast.NOTHING ->
409 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) in
410 Ast0.CONTEXT(ref(new_text,tinfo1,tinfo2))
411 | Ast0.MIXED(mc) ->
412 let (text,tinfo1,tinfo2) = !mc in
413 let new_text =
414 match text with
415 Ast.BEFORE(bef) ->
416 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]])
417 | Ast.AFTER(aft) ->
418 Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]])
419 | Ast.BEFOREAFTER(bef,aft) ->
420 Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]])
421 | Ast.NOTHING ->
422 Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) in
423 Ast0.MIXED(ref(new_text,tinfo1,tinfo2))
424 | _ -> failwith "unexpected plus code" in
425 Ast0.set_mcodekind s new_mcodekind;
426 Compute_lines.statement s
427
428(* ---------------------------------------------------------------------- *)
429
430let is_dots x =
431 match Ast0.unwrap x with
432 Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_)
433 | Ast0.Nest(_,_,_,_,_) -> true
434 | _ -> false
435
436let all_minus s =
437 match Ast0.get_mcodekind s with
438 Ast0.MINUS(_) -> true
439 | _ -> false
440
441let rec unchanged_minus s =
442 match Ast0.get_mcodekind s with
443 Ast0.MINUS(mc) -> (match !mc with ([],_) -> true | _ -> false)
444 | _ -> false
445
446let rec do_branch s =
447 if unchanged_minus s
448 then
449 Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(add_braces s))
450 else
451 match Ast0.unwrap s with
452 Ast0.Disj(starter,statement_dots_list,mids,ender) ->
453 let stmts =
454 List.map
455 (function s ->
456 match Ast0.unwrap s with
457 Ast0.DOTS([s]) ->
458 Ast0.rewrap s (Ast0.DOTS([do_branch s]))
459 | Ast0.DOTS(_) -> s
460 | _ -> failwith "not supported")
461 statement_dots_list in
462 Ast0.rewrap s (Ast0.Disj(starter,stmts,mids,ender))
463 | _ -> s
464
465let rec statement dots_before dots_after s =
466 let do_one s =
467 if dots_before && dots_after
468 then
469 if unchanged_minus s
470 then
471 (let with_braces = add_braces s in
472 Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(with_braces)))
473 else if adding_something s
474 then
475 (let with_braces = add_braces s in
476 Ast0.set_dots_bef_aft s (Ast0.AddingBetweenDots(with_braces)))
477 else s
478 else s in
479
480 match Ast0.unwrap s with
481 Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
482 (* true for close brace, because that represents any way we can
483 exit the function, which is not necessarily followed by an explicit
484 close brace. *)
485 Ast0.rewrap s
486 (Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace,
487 statement_dots false true body,
488 rbrace))
489 | Ast0.Decl(_,_) -> s
490 | Ast0.Seq(lbrace,body,rbrace) ->
491 Ast0.rewrap s
492 (Ast0.Seq(lbrace,statement_dots false false body,rbrace))
493 | Ast0.ExprStatement(exp,sem) -> do_one s
494 | Ast0.IfThen(iff,lp,exp,rp,branch1,x) ->
495 do_one
496 (Ast0.rewrap s
497 (Ast0.IfThen(iff,lp,exp,rp,statement false false branch1,x)))
498 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,x) ->
499 do_one
500 (Ast0.rewrap s
501 (Ast0.IfThenElse
502 (iff,lp,exp,rp,
503 statement false false branch1,els,
504 statement false false branch2,x)))
505 | Ast0.While(whl,lp,exp,rp,body,x) ->
506 do_one
507 (Ast0.rewrap s
508 (Ast0.While(whl,lp,exp,rp,statement false false body,x)))
509 | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
510 do_one
511 (Ast0.rewrap s
512 (Ast0.Do(d,statement false false body,whl,lp,exp,rp,sem)))
513 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,x) ->
514 do_one
515 (Ast0.rewrap s
516 (Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,
517 statement false false body,x)))
518 | Ast0.Iterator(nm,lp,args,rp,body,x) ->
519 do_one
520 (Ast0.rewrap s
521 (Ast0.Iterator(nm,lp,args,rp,statement false false body,x)))
522 | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
523 do_one
524 (Ast0.rewrap s
525 (Ast0.Switch(switch,lp,exp,rp,lb,
526 Ast0.rewrap cases
527 (Ast0.DOTS(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
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)
568 | Ast0.OptCase(case) -> Ast0.OptCase(case_line c))
faf9a90c 569
34e49164
C
570and do_statement_dots dots_before dots_after = function
571 [] -> []
572 | [x] -> [statement dots_before dots_after x]
573 | dots::rest when is_dots dots ->
574 dots::(do_statement_dots true dots_after rest)
575 | x::(dots::_ as rest) when is_dots dots ->
576 (statement dots_before true x)::
577 do_statement_dots false dots_after rest
578 | x::rest ->
579 (statement dots_before false x)::
580 do_statement_dots false dots_after rest
faf9a90c 581
34e49164
C
582and statement_dots dots_before dots_after d =
583 Ast0.rewrap d
584 (match Ast0.unwrap d with
585 Ast0.DOTS(l) ->
586 Ast0.DOTS(do_statement_dots dots_before dots_after l)
587 | Ast0.CIRCLES(l) ->
588 Ast0.CIRCLES(do_statement_dots dots_before dots_after l)
589 | Ast0.STARS(l) ->
590 Ast0.STARS(do_statement_dots dots_before dots_after l))
591
592let top_level t =
593 Ast0.rewrap t
594 (match Ast0.unwrap t with
595 Ast0.DECL(stmt_dots) -> Ast0.DECL(statement true true stmt_dots)
596 | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots true true stmt_dots)
597 | t -> t)
598
599let single_statement l =
600 if !Flag_parsing_cocci.sgrep_mode then l else List.map top_level l