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.
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.
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.
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/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
49 (* detect statements that are between dots in the minus code, because they
50 may need a special treatment if they are if branches *)
52 module Ast0
= Ast0_cocci
53 module Ast
= Ast_cocci
54 module V0
= Visitor_ast0
55 module VT0
= Visitor_ast0_types
57 (* --------------------------------------------------------------------- *)
58 (* --------------------------------------------------------------------- *)
62 match Ast0.undots l
with
67 match List.rev
(Ast0.undots l
) with
71 let modif_before_mcode mc
=
72 match Ast0.get_mcode_mcodekind mc
with
73 Ast0.MINUS mc
-> true (*conservative; don't want to hunt right for + code*)
74 | Ast0.PLUS _
-> failwith
"not possible"
77 (Ast.BEFORE _
,_
,_
) -> true
78 | (Ast.BEFOREAFTER _
,_
,_
) -> true
80 | Ast0.MIXED mc
-> true (* don't think mcode can be mixed *)
82 let modif_after_mcodekind = function
83 Ast0.MINUS mc
-> true (*conservative; don't want to hunt right for + code*)
84 | Ast0.PLUS _
-> failwith
"not possible"
87 (Ast.AFTER _
,_
,_
) -> true
88 | (Ast.BEFOREAFTER _
,_
,_
) -> true
90 | Ast0.MIXED mc
-> true (* don't think mcode can be mixed *)
92 let modif_after_mcode mc
= modif_after_mcodekind (Ast0.get_mcode_mcodekind mc
)
98 Ast.StatementTag
(_
) | Ast.StmtDotsTag
(_
)
99 | Ast.DeclarationTag
(_
) | Ast.DeclDotsTag
(_
) -> true | _
-> false))
102 match Ast0.get_mcodekind x
with
103 Ast0.PLUS _
-> failwith
"not possible"
106 (* do better for the common case of replacing a stmt by another one *)
107 ([[Ast.StatementTag
(s
)]],ti
) ->
108 (match Ast.unwrap s
with
109 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
110 | _
-> mc
:= ([[Ast.StatementTag
(s
)]],ti
); false)
112 | Ast0.CONTEXT mc
| Ast0.MIXED mc
->
114 (Ast.BEFORE _
,_
,_
) -> true
115 | (Ast.BEFOREAFTER _
,_
,_
) -> true
119 match Ast0.get_mcodekind x
with
120 Ast0.PLUS _
-> failwith
"not possible"
123 (* do better for the common case of replacing a stmt by another one *)
124 ([[Ast.StatementTag
(s
)]],ti
) ->
125 (match Ast.unwrap s
with
126 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
127 | _
-> mc
:= ([[Ast.StatementTag
(s
)]],ti
); false)
128 | (l
,_
) when any_statements l
-> true
129 | (l
,ti
) -> mc
:= (l
,ti
); false)
130 | Ast0.CONTEXT mc
| Ast0.MIXED mc
->
132 (Ast.AFTER _
,_
,_
) -> true
133 | (Ast.BEFOREAFTER _
,_
,_
) -> true
137 let rec left_ident i
=
139 match Ast0.unwrap i
with
140 Ast0.Id
(name
) -> modif_before_mcode name
141 | Ast0.MetaId
(name
,_
,_
) -> modif_before_mcode name
142 | Ast0.MetaFunc
(name
,_
,_
) -> modif_before_mcode name
143 | Ast0.MetaLocalFunc
(name
,_
,_
) -> modif_before_mcode name
144 | Ast0.OptIdent
(id
) -> left_ident id
145 | Ast0.UniqueIdent
(id
) -> left_ident id
147 (* --------------------------------------------------------------------- *)
150 let rec left_expression e
=
152 match Ast0.unwrap e
with
153 Ast0.Ident
(id
) -> left_ident id
154 | Ast0.Constant
(const
) -> modif_before_mcode const
155 | Ast0.FunCall
(fn
,lp
,args
,rp
) -> left_expression fn
156 | Ast0.Assignment
(left
,op
,right
,_
) -> left_expression left
157 | Ast0.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) -> left_expression exp1
158 | Ast0.Postfix
(exp
,op
) -> left_expression exp
159 | Ast0.Infix
(exp
,op
) -> modif_before_mcode op
160 | Ast0.Unary
(exp
,op
) -> modif_before_mcode op
161 | Ast0.Binary
(left
,op
,right
) -> left_expression left
162 | Ast0.Nested
(left
,op
,right
) -> left_expression left
163 | Ast0.Paren
(lp
,exp
,rp
) -> modif_before_mcode lp
164 | Ast0.ArrayAccess
(exp1
,lb
,exp2
,rb
) -> left_expression exp1
165 | Ast0.RecordAccess
(exp
,pt
,field
) -> left_expression exp
166 | Ast0.RecordPtAccess
(exp
,ar
,field
) -> left_expression exp
167 | Ast0.Cast
(lp
,ty
,rp
,exp
) -> modif_before_mcode lp
168 | Ast0.SizeOfExpr
(szf
,exp
) -> modif_before_mcode szf
169 | Ast0.SizeOfType
(szf
,lp
,ty
,rp
) -> modif_before_mcode szf
170 | Ast0.TypeExp
(ty
) -> left_typeC ty
171 | Ast0.MetaErr
(name
,_
,_
) -> modif_before_mcode name
172 | Ast0.MetaExpr
(name
,_
,ty
,_
,_
) -> modif_before_mcode name
173 | Ast0.MetaExprList
(name
,_
,_
) -> modif_before_mcode name
174 | Ast0.EComma
(cm
) -> modif_before_mcode cm
175 | Ast0.DisjExpr
(_
,exp_list
,_
,_
) -> List.exists
left_expression exp_list
176 | Ast0.NestExpr
(starter
,expr_dots
,ender
,_
,multi
) ->
177 left_dots left_expression expr_dots
178 | Ast0.Edots
(dots
,_
) | Ast0.Ecircles
(dots
,_
) | Ast0.Estars
(dots
,_
) -> false
179 | Ast0.OptExp
(exp
) -> left_expression exp
180 | Ast0.UniqueExp
(exp
) -> left_expression exp
182 (* --------------------------------------------------------------------- *)
187 match Ast0.unwrap t
with
188 Ast0.ConstVol
(cv
,ty
) -> modif_before_mcode cv
189 | Ast0.BaseType
(ty
,strings
) -> modif_before_mcode (List.hd strings
)
190 | Ast0.Signed
(sgn
,ty
) -> modif_before_mcode sgn
191 | Ast0.Pointer
(ty
,star
) -> left_typeC ty
192 | Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) -> left_typeC ty
193 | Ast0.FunctionType
(Some ty
,lp1
,params
,rp1
) -> left_typeC ty
194 | Ast0.FunctionType
(None
,lp1
,params
,rp1
) -> modif_before_mcode lp1
195 | Ast0.Array
(ty
,lb
,size
,rb
) -> left_typeC ty
196 | Ast0.EnumName
(kind
,name
) -> modif_before_mcode kind
197 | Ast0.EnumDef
(ty
,lb
,ids
,rb
) -> left_typeC ty
198 | Ast0.StructUnionName
(kind
,name
) -> modif_before_mcode kind
199 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) -> left_typeC ty
200 | Ast0.TypeName
(name
) -> modif_before_mcode name
201 | Ast0.MetaType
(name
,_
) -> modif_before_mcode name
202 | Ast0.DisjType
(lp
,types
,mids
,rp
) -> List.exists left_typeC types
203 | Ast0.OptType
(ty
) -> left_typeC ty
204 | Ast0.UniqueType
(ty
) -> left_typeC ty
206 (* --------------------------------------------------------------------- *)
207 (* Variable declaration *)
208 (* Even if the Cocci program specifies a list of declarations, they are
209 split out into multiple declarations of a single variable each. *)
211 and left_declaration d
=
213 match Ast0.unwrap d
with
214 Ast0.MetaDecl
(name
,_
) | Ast0.MetaField
(name
,_
) -> modif_before_mcode name
215 | Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
) -> modif_before_mcode stg
216 | Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
) -> left_typeC ty
217 | Ast0.UnInit
(Some stg
,ty
,id
,sem
) -> modif_before_mcode stg
218 | Ast0.UnInit
(None
,ty
,id
,sem
) -> left_typeC ty
219 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) -> left_ident name
220 | Ast0.TyDecl
(ty
,sem
) -> left_typeC ty
221 | Ast0.Typedef
(stg
,ty
,id
,sem
) -> modif_before_mcode stg
222 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> List.exists left_declaration decls
223 | Ast0.Ddots
(dots
,_
) -> false
224 | Ast0.OptDecl
(decl
) -> left_declaration decl
225 | Ast0.UniqueDecl
(decl
) -> left_declaration decl
227 and right_declaration d
=
229 match Ast0.unwrap d
with
230 Ast0.MetaDecl
(name
,_
) | Ast0.MetaField
(name
,_
) -> modif_before_mcode name
231 | Ast0.Init
(_
,ty
,id
,eq
,ini
,sem
) -> modif_after_mcode sem
232 | Ast0.UnInit
(_
,ty
,id
,sem
) -> modif_after_mcode sem
233 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) -> modif_after_mcode sem
234 | Ast0.TyDecl
(ty
,sem
) -> modif_after_mcode sem
235 | Ast0.Typedef
(stg
,ty
,id
,sem
) -> modif_after_mcode sem
236 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> List.exists right_declaration decls
237 | Ast0.Ddots
(dots
,_
) -> false
238 | Ast0.OptDecl
(decl
) -> right_declaration decl
239 | Ast0.UniqueDecl
(decl
) -> right_declaration decl
241 (* --------------------------------------------------------------------- *)
244 and left_statement s
=
246 match Ast0.unwrap s
with
247 Ast0.FunDecl
(_
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
248 (* irrelevant *) false
249 | Ast0.Decl
(_
,decl
) -> left_declaration decl
250 | Ast0.Seq
(lbrace
,body
,rbrace
) -> modif_before_mcode lbrace
251 | Ast0.ExprStatement
(exp
,sem
) -> left_expression exp
252 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,(info
,aft
)) -> modif_before_mcode iff
253 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,(info
,aft
)) ->
254 modif_before_mcode iff
255 | Ast0.While
(whl
,lp
,exp
,rp
,body
,(info
,aft
)) -> modif_before_mcode whl
256 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) -> modif_before_mcode d
257 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,(info
,aft
)) ->
258 modif_before_mcode fr
259 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,(info
,aft
)) -> left_ident nm
260 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
261 modif_before_mcode switch
262 | Ast0.Break
(br
,sem
) -> modif_before_mcode br
263 | Ast0.Continue
(cont
,sem
) -> modif_before_mcode cont
264 | Ast0.Label
(l
,dd
) -> left_ident l
265 | Ast0.Goto
(goto
,l
,sem
) -> modif_before_mcode goto
266 | Ast0.Return
(ret
,sem
) -> modif_before_mcode ret
267 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> modif_before_mcode ret
268 | Ast0.MetaStmt
(name
,pure
) -> modif_before_mcode name
269 | Ast0.MetaStmtList
(name
,_
) -> modif_before_mcode name
270 | Ast0.Disj
(_
,statement_dots_list
,_
,_
) ->
271 List.exists
(left_dots left_statement
) statement_dots_list
272 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
273 left_dots left_statement stmt_dots
274 | Ast0.Exp
(exp
) -> false (* can only be replaced by an expression *)
275 | Ast0.TopExp
(exp
) -> false (* as above *)
276 | Ast0.Ty
(ty
) -> false (* can only be replaced by a type *)
277 | Ast0.TopInit
(init
) -> false (* can only be replaced by an init *)
278 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> false
279 | Ast0.Include
(inc
,s
) -> modif_before_mcode inc
280 | Ast0.Define
(def
,id
,params
,body
) -> modif_before_mcode def
281 | Ast0.OptStm
(re
) -> left_statement re
282 | Ast0.UniqueStm
(re
) -> left_statement re
284 and right_statement s
=
286 match Ast0.unwrap s
with
287 Ast0.FunDecl
(_
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
288 (* irrelevant *) false
289 | Ast0.Decl
(_
,decl
) -> right_declaration decl
290 | Ast0.Seq
(lbrace
,body
,rbrace
) -> modif_after_mcode rbrace
291 | Ast0.ExprStatement
(exp
,sem
) -> modif_after_mcode sem
292 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,(info
,aft
)) -> modif_after_mcodekind aft
293 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,(info
,aft
)) ->
294 modif_after_mcodekind aft
295 | Ast0.While
(whl
,lp
,exp
,rp
,body
,(info
,aft
)) -> modif_after_mcodekind aft
296 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) -> modif_after_mcode sem
297 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,(info
,aft
)) ->
298 modif_after_mcodekind aft
299 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,(info
,aft
)) ->
300 modif_after_mcodekind aft
301 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) -> modif_after_mcode rb
302 | Ast0.Break
(br
,sem
) -> modif_after_mcode sem
303 | Ast0.Continue
(cont
,sem
) -> modif_after_mcode sem
304 | Ast0.Label
(l
,dd
) -> modif_after_mcode dd
305 | Ast0.Goto
(goto
,l
,sem
) -> modif_after_mcode sem
306 | Ast0.Return
(ret
,sem
) -> modif_after_mcode sem
307 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> modif_after_mcode sem
308 | Ast0.MetaStmt
(name
,pure
) -> modif_after_mcode name
309 | Ast0.MetaStmtList
(name
,_
) -> modif_after_mcode name
310 | Ast0.Disj
(_
,statement_dots_list
,_
,_
) ->
311 List.exists
(right_dots right_statement
) statement_dots_list
312 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
313 right_dots right_statement stmt_dots
314 | Ast0.Exp
(exp
) -> false (* can only be replaced by an expression *)
315 | Ast0.TopExp
(exp
) -> false (* as above *)
316 | Ast0.Ty
(ty
) -> false (* can only be replaced by a type *)
317 | Ast0.TopInit
(init
) -> false (* can only be replaced by an init *)
318 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> false
319 | Ast0.Include
(inc
,s
) -> modif_after_mcode s
320 | Ast0.Define
(def
,id
,params
,body
) -> right_dots right_statement body
321 | Ast0.OptStm
(re
) -> right_statement re
322 | Ast0.UniqueStm
(re
) -> right_statement re
324 (* --------------------------------------------------------------------- *)
327 (* A very coarse approximation. We would really only like to return true
328 if a new statement is added. For this it would be best to correlate with the
329 plus slice. Or at least be sure that the new stuff is on the far left or
332 let rec adding_something s
=
333 match Ast0.get_mcodekind s
with
336 (* do better for the common case of replacing a stmt by another one *)
337 ([[Ast.StatementTag
(s
)]],ti
) ->
338 (match Ast.unwrap s
with
339 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
340 | _
-> mc
:= ([[Ast.StatementTag
(s
)]],ti
); false)
342 | Ast0.CONTEXT
(mc
) ->
343 let (text
,tinfo1
,tinfo2
) = !mc
in
344 (match text
with Ast.NOTHING
-> false | _
-> true)
346 not
(contains_only_minus
.VT0.combiner_rec_statement s
) (*&&
347 (left_statement s) or (right_statement s)*)
348 | _
-> failwith
"unexpected plus code"
350 (* why do we need this; MINUS should mean the same thing *)
351 and contains_only_minus
=
352 let bind x y
= x
&& y
in
353 let option_default = true in
354 let mcodekind = function
359 | Ast0.CONTEXT
(mc
) -> false
361 let mcode (_
,_
,_
,mc
,_
,_
) = mcodekind mc
in
363 let donothing r k e
= mcodekind (Ast0.get_mcodekind e
) && k e
in
366 match Ast0.unwrap e
with
367 Ast0.DOTS
([]) | Ast0.CIRCLES
([]) | Ast0.STARS
([]) -> true
370 let expression r k e
=
371 mcodekind (Ast0.get_mcodekind e
) &&
372 match Ast0.unwrap e
with
373 Ast0.DisjExpr
(starter
,expr_list
,mids
,ender
) ->
374 List.for_all r
.VT0.combiner_rec_expression expr_list
377 let declaration r k e
=
378 mcodekind (Ast0.get_mcodekind e
) &&
379 match Ast0.unwrap e
with
380 Ast0.DisjDecl
(starter
,decls
,mids
,ender
) ->
381 List.for_all r
.VT0.combiner_rec_declaration decls
385 mcodekind (Ast0.get_mcodekind e
) &&
386 match Ast0.unwrap e
with
387 Ast0.DisjType
(starter
,types
,mids
,ender
) ->
388 List.for_all r
.VT0.combiner_rec_typeC types
391 let statement r k e
=
392 mcodekind (Ast0.get_mcodekind e
) &&
393 match Ast0.unwrap e
with
394 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
395 List.for_all r
.VT0.combiner_rec_statement_dots statement_dots_list
398 let case_line r k e
=
399 mcodekind (Ast0.get_mcodekind e
) &&
400 match Ast0.unwrap e
with
401 Ast0.DisjCase
(starter
,case_list
,mids
,ender
) ->
402 List.for_all r
.VT0.combiner_rec_case_line case_list
405 V0.flat_combiner
bind option_default
406 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
407 dots dots dots dots dots dots
408 donothing expression typeC donothing donothing declaration
409 statement case_line donothing
412 (* needs a special case when there is a Disj or an empty DOTS *)
413 (* ---------------------------------------------------------------------- *)
418 if (acpi_device_dir(device))
420 remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
421 + acpi_device_dir(device) = NULL;
424 The last two + lines get associated with the end of the if, not with the
425 branch, so the braces get added in oddly.
428 let add_braces orig_s
=
430 (Iso_pattern.rebuild_mcode None
).VT0.rebuilder_rec_statement orig_s
in
432 match Ast0.get_mcodekind
s with
434 let (text
,tinfo
) = !mc
in
435 Ast0.MINUS
(ref([Ast.mkToken
"{"]::text
@[[Ast.mkToken
"}"]],tinfo
))
436 | Ast0.CONTEXT
(mc
) ->
437 let (text
,tinfo1
,tinfo2
) = !mc
in
439 (* this is going to be a mess if we allow it to be iterable...
440 there would be one level of braces for every added things.
441 need to come up with something better, or just add {} in the
445 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,[[Ast.mkToken
"}"]],
447 | Ast.AFTER
(aft
,_
) ->
448 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],aft
@[[Ast.mkToken
"}"]],
450 | Ast.BEFOREAFTER
(bef
,aft
,_
) ->
451 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,aft
@[[Ast.mkToken
"}"]],
454 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],[[Ast.mkToken
"}"]],
456 Ast0.CONTEXT
(ref(new_text,tinfo1
,tinfo2
))
458 let (text
,tinfo1
,tinfo2
) = !mc
in
462 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,[[Ast.mkToken
"}"]],
464 | Ast.AFTER
(aft
,_
) ->
465 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],aft
@[[Ast.mkToken
"}"]],
467 | Ast.BEFOREAFTER
(bef
,aft
,_
) ->
468 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,aft
@[[Ast.mkToken
"}"]],
471 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],[[Ast.mkToken
"}"]],
473 Ast0.MIXED
(ref(new_text,tinfo1
,tinfo2
))
474 | _
-> failwith
"unexpected plus code" in
475 Ast0.set_mcodekind
s new_mcodekind;
476 Compute_lines.compute_statement_lines
true s
478 (* ---------------------------------------------------------------------- *)
481 match Ast0.unwrap x
with
482 Ast0.Dots
(_
,_
) | Ast0.Circles
(_
,_
) | Ast0.Stars
(_
,_
)
483 | Ast0.Nest
(_
,_
,_
,_
,_
) -> true
487 match Ast0.get_mcodekind
s with
488 Ast0.MINUS
(_
) -> true
491 let rec unchanged_minus s =
492 match Ast0.get_mcodekind
s with
493 Ast0.MINUS
(mc
) -> (match !mc
with ([],_
) -> true | _
-> false)
496 let rec do_branch s =
499 Ast0.set_dots_bef_aft
s (Ast0.DroppingBetweenDots
(add_braces s))
501 match Ast0.unwrap
s with
502 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
506 match Ast0.unwrap
s with
508 Ast0.rewrap
s (Ast0.DOTS
([do_branch s]))
510 | _
-> failwith
"not supported")
511 statement_dots_list
in
512 Ast0.rewrap
s (Ast0.Disj
(starter
,stmts,mids
,ender
))
515 let rec statement dots_before dots_after
s =
517 if dots_before
&& dots_after
521 (let with_braces = add_braces s in
522 Ast0.set_dots_bef_aft
s (Ast0.DroppingBetweenDots
(with_braces)))
523 else if adding_something s
525 (let with_braces = add_braces s in
526 Ast0.set_dots_bef_aft
s (Ast0.AddingBetweenDots
(with_braces)))
530 match Ast0.unwrap
s with
531 Ast0.FunDecl
(x
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
532 (* true for close brace, because that represents any way we can
533 exit the function, which is not necessarily followed by an explicit
536 (Ast0.FunDecl
(x
,fninfo
,name
,lp
,params
,rp
,lbrace
,
537 statement_dots
false true body
,
539 | Ast0.Decl
(_
,_
) -> s
540 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
542 (Ast0.Seq
(lbrace
,statement_dots
false false body
,rbrace
))
543 | Ast0.ExprStatement
(exp
,sem
) -> do_one s
544 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,x
) ->
547 (Ast0.IfThen
(iff
,lp
,exp
,rp
,statement false false branch1
,x
)))
548 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,x
) ->
553 statement false false branch1
,els
,
554 statement false false branch2
,x
)))
555 | Ast0.While
(whl
,lp
,exp
,rp
,body
,x
) ->
558 (Ast0.While
(whl
,lp
,exp
,rp
,statement false false body
,x
)))
559 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) ->
562 (Ast0.Do
(d
,statement false false body
,whl
,lp
,exp
,rp
,sem
)))
563 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,x
) ->
566 (Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,
567 statement false false body
,x
)))
568 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,x
) ->
571 (Ast0.Iterator
(nm
,lp
,args
,rp
,statement false false body
,x
)))
572 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
575 (Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,
578 (List.map
case_line (Ast0.undots cases
))),
580 | Ast0.Break
(br
,sem
) -> do_one s
581 | Ast0.Continue
(cont
,sem
) -> do_one s
582 | Ast0.Label
(l
,dd
) -> do_one s
583 | Ast0.Goto
(goto
,l
,sem
) -> do_one s
584 | Ast0.Return
(ret
,sem
) -> do_one s
585 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> do_one s
586 | Ast0.MetaStmt
(name
,_
) -> do_one s
587 | Ast0.MetaStmtList
(name
,_
) -> do_one s
588 | Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
591 List.map
(statement_dots dots_before dots_after
)
594 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
595 (match Ast0.get_mcode_mcodekind starter
with
596 Ast0.MINUS _
-> (* everything removed, like -... *) s
600 (starter
,statement_dots
true true stmt_dots
,ender
,
603 | Ast0.TopExp
(exp
) -> s
605 | Ast0.TopInit
(init
) -> s
606 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> s
607 | Ast0.Include
(inc
,string) -> s (* doesn't affect the need for braces *)
608 | Ast0.Define
(def
,id
,params
,body
) -> s (* same as include *)
611 (Ast0.OptStm
(statement dots_before dots_after re
))
612 | Ast0.UniqueStm
(re
) ->
614 (Ast0.UniqueStm
(statement dots_before dots_after re
))
618 (match Ast0.unwrap c
with
619 Ast0.Default
(def
,colon
,code
) ->
620 Ast0.Default
(def
,colon
,statement_dots
false false code
)
621 | Ast0.Case
(case
,exp
,colon
,code
) ->
622 Ast0.Case
(case
,exp
,colon
,statement_dots
false false code
)
623 | Ast0.DisjCase
(starter
,case_lines
,mids
,ender
) ->
624 Ast0.DisjCase
(starter
,List.map
case_line case_lines
,mids
,ender
)
625 | Ast0.OptCase
(case
) -> Ast0.OptCase
(case_line c
))
627 and do_statement_dots dots_before dots_after
= function
629 | [x
] -> [statement dots_before dots_after x
]
630 | dots::rest
when is_dots dots ->
631 dots::(do_statement_dots
true dots_after rest
)
632 | x
::(dots::_
as rest
) when is_dots dots ->
633 (statement dots_before
true x
)::
634 do_statement_dots
false dots_after rest
636 (statement dots_before
false x
)::
637 do_statement_dots
false dots_after rest
639 and statement_dots dots_before dots_after d
=
641 (match Ast0.unwrap d
with
643 Ast0.DOTS
(do_statement_dots dots_before dots_after l
)
645 Ast0.CIRCLES
(do_statement_dots dots_before dots_after l
)
647 Ast0.STARS
(do_statement_dots dots_before dots_after l
))
651 (match Ast0.unwrap t
with
652 Ast0.DECL
(stmt_dots
) -> Ast0.DECL
(statement true true stmt_dots
)
653 | Ast0.CODE
(stmt_dots
) -> Ast0.CODE
(statement_dots
true true stmt_dots
)
656 let single_statement l
=
657 if !Flag_parsing_cocci.sgrep_mode
then l
else List.map
top_level l