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