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