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