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