2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
23 (* detect statements that are between dots in the minus code, because they
24 may need a special treatment if they are if branches *)
26 module Ast0
= Ast0_cocci
27 module Ast
= Ast_cocci
28 module V0
= Visitor_ast0
29 module VT0
= Visitor_ast0_types
31 (* --------------------------------------------------------------------- *)
32 (* --------------------------------------------------------------------- *)
36 match Ast0.undots l
with
41 match List.rev
(Ast0.undots l
) with
45 let modif_before_mcode mc
=
46 match Ast0.get_mcode_mcodekind mc
with
47 Ast0.MINUS mc
-> true (*conservative; don't want to hunt right for + code*)
48 | Ast0.PLUS _
-> failwith
"not possible"
51 (Ast.BEFORE _
,_
,_
) -> true
52 | (Ast.BEFOREAFTER _
,_
,_
) -> true
54 | Ast0.MIXED mc
-> true (* don't think mcode can be mixed *)
56 let modif_after_mcodekind = function
57 Ast0.MINUS mc
-> true (*conservative; don't want to hunt right for + code*)
58 | Ast0.PLUS _
-> failwith
"not possible"
61 (Ast.AFTER _
,_
,_
) -> true
62 | (Ast.BEFOREAFTER _
,_
,_
) -> true
64 | Ast0.MIXED mc
-> true (* don't think mcode can be mixed *)
66 let modif_after_mcode mc
= modif_after_mcodekind (Ast0.get_mcode_mcodekind mc
)
72 Ast.StatementTag
(_
) | Ast.StmtDotsTag
(_
)
73 | Ast.DeclarationTag
(_
) | Ast.DeclDotsTag
(_
) -> true | _
-> false))
76 match Ast0.get_mcodekind x
with
77 Ast0.PLUS _
-> failwith
"not possible"
80 (* do better for the common case of replacing a stmt by another one *)
81 ([[Ast.StatementTag
(s
)]],ti
) ->
82 (match Ast.unwrap s
with
83 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
84 | _
-> mc
:= ([[Ast.StatementTag
(s
)]],ti
); false)
86 | Ast0.CONTEXT mc
| Ast0.MIXED mc
->
88 (Ast.BEFORE _
,_
,_
) -> true
89 | (Ast.BEFOREAFTER _
,_
,_
) -> true
93 match Ast0.get_mcodekind x
with
94 Ast0.PLUS _
-> failwith
"not possible"
97 (* do better for the common case of replacing a stmt by another one *)
98 ([[Ast.StatementTag
(s
)]],ti
) ->
99 (match Ast.unwrap s
with
100 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
101 | _
-> mc
:= ([[Ast.StatementTag
(s
)]],ti
); false)
102 | (l
,_
) when any_statements l
-> true
103 | (l
,ti
) -> mc
:= (l
,ti
); false)
104 | Ast0.CONTEXT mc
| Ast0.MIXED mc
->
106 (Ast.AFTER _
,_
,_
) -> true
107 | (Ast.BEFOREAFTER _
,_
,_
) -> true
111 let rec left_ident i
=
113 match Ast0.unwrap i
with
114 Ast0.Id
(name
) -> modif_before_mcode name
115 | Ast0.MetaId
(name
,_
,_
) -> modif_before_mcode name
116 | Ast0.MetaFunc
(name
,_
,_
) -> modif_before_mcode name
117 | Ast0.MetaLocalFunc
(name
,_
,_
) -> modif_before_mcode name
118 | Ast0.OptIdent
(id
) -> left_ident id
119 | Ast0.UniqueIdent
(id
) -> left_ident id
121 (* --------------------------------------------------------------------- *)
124 let rec left_expression e
=
126 match Ast0.unwrap e
with
127 Ast0.Ident
(id
) -> left_ident id
128 | Ast0.Constant
(const
) -> modif_before_mcode const
129 | Ast0.FunCall
(fn
,lp
,args
,rp
) -> left_expression fn
130 | Ast0.Assignment
(left
,op
,right
,_
) -> left_expression left
131 | Ast0.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) -> left_expression exp1
132 | Ast0.Postfix
(exp
,op
) -> left_expression exp
133 | Ast0.Infix
(exp
,op
) -> modif_before_mcode op
134 | Ast0.Unary
(exp
,op
) -> modif_before_mcode op
135 | Ast0.Binary
(left
,op
,right
) -> left_expression left
136 | Ast0.Nested
(left
,op
,right
) -> left_expression left
137 | Ast0.Paren
(lp
,exp
,rp
) -> modif_before_mcode lp
138 | Ast0.ArrayAccess
(exp1
,lb
,exp2
,rb
) -> left_expression exp1
139 | Ast0.RecordAccess
(exp
,pt
,field
) -> left_expression exp
140 | Ast0.RecordPtAccess
(exp
,ar
,field
) -> left_expression exp
141 | Ast0.Cast
(lp
,ty
,rp
,exp
) -> modif_before_mcode lp
142 | Ast0.SizeOfExpr
(szf
,exp
) -> modif_before_mcode szf
143 | Ast0.SizeOfType
(szf
,lp
,ty
,rp
) -> modif_before_mcode szf
144 | Ast0.TypeExp
(ty
) -> left_typeC ty
145 | Ast0.MetaErr
(name
,_
,_
) -> modif_before_mcode name
146 | Ast0.MetaExpr
(name
,_
,ty
,_
,_
) -> modif_before_mcode name
147 | Ast0.MetaExprList
(name
,_
,_
) -> modif_before_mcode name
148 | Ast0.EComma
(cm
) -> modif_before_mcode cm
149 | Ast0.DisjExpr
(_
,exp_list
,_
,_
) -> List.exists
left_expression exp_list
150 | Ast0.NestExpr
(starter
,expr_dots
,ender
,_
,multi
) ->
151 left_dots left_expression expr_dots
152 | Ast0.Edots
(dots
,_
) | Ast0.Ecircles
(dots
,_
) | Ast0.Estars
(dots
,_
) -> false
153 | Ast0.OptExp
(exp
) -> left_expression exp
154 | Ast0.UniqueExp
(exp
) -> left_expression exp
156 (* --------------------------------------------------------------------- *)
161 match Ast0.unwrap t
with
162 Ast0.ConstVol
(cv
,ty
) -> modif_before_mcode cv
163 | Ast0.BaseType
(ty
,strings
) -> modif_before_mcode (List.hd strings
)
164 | Ast0.Signed
(sgn
,ty
) -> modif_before_mcode sgn
165 | Ast0.Pointer
(ty
,star
) -> left_typeC ty
166 | Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) -> left_typeC ty
167 | Ast0.FunctionType
(Some ty
,lp1
,params
,rp1
) -> left_typeC ty
168 | Ast0.FunctionType
(None
,lp1
,params
,rp1
) -> modif_before_mcode lp1
169 | Ast0.Array
(ty
,lb
,size
,rb
) -> left_typeC ty
170 | Ast0.EnumName
(kind
,name
) -> modif_before_mcode kind
171 | Ast0.StructUnionName
(kind
,name
) -> modif_before_mcode kind
172 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) -> left_typeC ty
173 | Ast0.TypeName
(name
) -> modif_before_mcode name
174 | Ast0.MetaType
(name
,_
) -> modif_before_mcode name
175 | Ast0.DisjType
(lp
,types
,mids
,rp
) -> List.exists left_typeC types
176 | Ast0.OptType
(ty
) -> left_typeC ty
177 | Ast0.UniqueType
(ty
) -> left_typeC ty
179 (* --------------------------------------------------------------------- *)
180 (* Variable declaration *)
181 (* Even if the Cocci program specifies a list of declarations, they are
182 split out into multiple declarations of a single variable each. *)
184 and left_declaration d
=
186 match Ast0.unwrap d
with
187 Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
) -> modif_before_mcode stg
188 | Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
) -> left_typeC ty
189 | Ast0.UnInit
(Some stg
,ty
,id
,sem
) -> modif_before_mcode stg
190 | Ast0.UnInit
(None
,ty
,id
,sem
) -> left_typeC ty
191 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) -> left_ident name
192 | Ast0.TyDecl
(ty
,sem
) -> left_typeC ty
193 | Ast0.Typedef
(stg
,ty
,id
,sem
) -> modif_before_mcode stg
194 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> List.exists left_declaration decls
195 | Ast0.Ddots
(dots
,_
) -> false
196 | Ast0.OptDecl
(decl
) -> left_declaration decl
197 | Ast0.UniqueDecl
(decl
) -> left_declaration decl
199 and right_declaration d
=
201 match Ast0.unwrap d
with
202 Ast0.Init
(_
,ty
,id
,eq
,ini
,sem
) -> modif_after_mcode sem
203 | Ast0.UnInit
(_
,ty
,id
,sem
) -> modif_after_mcode sem
204 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) -> modif_after_mcode sem
205 | Ast0.TyDecl
(ty
,sem
) -> modif_after_mcode sem
206 | Ast0.Typedef
(stg
,ty
,id
,sem
) -> modif_after_mcode sem
207 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> List.exists right_declaration decls
208 | Ast0.Ddots
(dots
,_
) -> false
209 | Ast0.OptDecl
(decl
) -> right_declaration decl
210 | Ast0.UniqueDecl
(decl
) -> right_declaration decl
212 (* --------------------------------------------------------------------- *)
215 and left_statement s
=
217 match Ast0.unwrap s
with
218 Ast0.FunDecl
(_
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
219 (* irrelevant *) false
220 | Ast0.Decl
(_
,decl
) -> left_declaration decl
221 | Ast0.Seq
(lbrace
,body
,rbrace
) -> modif_before_mcode lbrace
222 | Ast0.ExprStatement
(exp
,sem
) -> left_expression exp
223 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,(info
,aft
)) -> modif_before_mcode iff
224 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,(info
,aft
)) ->
225 modif_before_mcode iff
226 | Ast0.While
(whl
,lp
,exp
,rp
,body
,(info
,aft
)) -> modif_before_mcode whl
227 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) -> modif_before_mcode d
228 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,(info
,aft
)) ->
229 modif_before_mcode fr
230 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,(info
,aft
)) -> left_ident nm
231 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
232 modif_before_mcode switch
233 | Ast0.Break
(br
,sem
) -> modif_before_mcode br
234 | Ast0.Continue
(cont
,sem
) -> modif_before_mcode cont
235 | Ast0.Label
(l
,dd
) -> left_ident l
236 | Ast0.Goto
(goto
,l
,sem
) -> modif_before_mcode goto
237 | Ast0.Return
(ret
,sem
) -> modif_before_mcode ret
238 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> modif_before_mcode ret
239 | Ast0.MetaStmt
(name
,pure
) -> modif_before_mcode name
240 | Ast0.MetaStmtList
(name
,_
) -> modif_before_mcode name
241 | Ast0.Disj
(_
,statement_dots_list
,_
,_
) ->
242 List.exists
(left_dots left_statement
) statement_dots_list
243 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
244 left_dots left_statement stmt_dots
245 | Ast0.Exp
(exp
) -> false (* can only be replaced by an expression *)
246 | Ast0.TopExp
(exp
) -> false (* as above *)
247 | Ast0.Ty
(ty
) -> false (* can only be replaced by a type *)
248 | Ast0.TopInit
(init
) -> false (* can only be replaced by an init *)
249 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> false
250 | Ast0.Include
(inc
,s
) -> modif_before_mcode inc
251 | Ast0.Define
(def
,id
,params
,body
) -> modif_before_mcode def
252 | Ast0.OptStm
(re
) -> left_statement re
253 | Ast0.UniqueStm
(re
) -> left_statement re
255 and right_statement s
=
257 match Ast0.unwrap s
with
258 Ast0.FunDecl
(_
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
259 (* irrelevant *) false
260 | Ast0.Decl
(_
,decl
) -> right_declaration decl
261 | Ast0.Seq
(lbrace
,body
,rbrace
) -> modif_after_mcode rbrace
262 | Ast0.ExprStatement
(exp
,sem
) -> modif_after_mcode sem
263 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,(info
,aft
)) -> modif_after_mcodekind aft
264 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,(info
,aft
)) ->
265 modif_after_mcodekind aft
266 | Ast0.While
(whl
,lp
,exp
,rp
,body
,(info
,aft
)) -> modif_after_mcodekind aft
267 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) -> modif_after_mcode sem
268 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,(info
,aft
)) ->
269 modif_after_mcodekind aft
270 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,(info
,aft
)) ->
271 modif_after_mcodekind aft
272 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) -> modif_after_mcode rb
273 | Ast0.Break
(br
,sem
) -> modif_after_mcode sem
274 | Ast0.Continue
(cont
,sem
) -> modif_after_mcode sem
275 | Ast0.Label
(l
,dd
) -> modif_after_mcode dd
276 | Ast0.Goto
(goto
,l
,sem
) -> modif_after_mcode sem
277 | Ast0.Return
(ret
,sem
) -> modif_after_mcode sem
278 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> modif_after_mcode sem
279 | Ast0.MetaStmt
(name
,pure
) -> modif_after_mcode name
280 | Ast0.MetaStmtList
(name
,_
) -> modif_after_mcode name
281 | Ast0.Disj
(_
,statement_dots_list
,_
,_
) ->
282 List.exists
(right_dots right_statement
) statement_dots_list
283 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
284 right_dots right_statement stmt_dots
285 | Ast0.Exp
(exp
) -> false (* can only be replaced by an expression *)
286 | Ast0.TopExp
(exp
) -> false (* as above *)
287 | Ast0.Ty
(ty
) -> false (* can only be replaced by a type *)
288 | Ast0.TopInit
(init
) -> false (* can only be replaced by an init *)
289 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> false
290 | Ast0.Include
(inc
,s
) -> modif_after_mcode s
291 | Ast0.Define
(def
,id
,params
,body
) -> right_dots right_statement body
292 | Ast0.OptStm
(re
) -> right_statement re
293 | Ast0.UniqueStm
(re
) -> right_statement re
295 (* --------------------------------------------------------------------- *)
298 (* A very coarse approximation. We would really only like to return true
299 if a new statement is added. For this it would be best to correlate with the
300 plus slice. Or at least be sure that the new stuff is on the far left or
303 let rec adding_something s
=
304 match Ast0.get_mcodekind s
with
307 (* do better for the common case of replacing a stmt by another one *)
308 ([[Ast.StatementTag
(s
)]],ti
) ->
309 (match Ast.unwrap s
with
310 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
311 | _
-> mc
:= ([[Ast.StatementTag
(s
)]],ti
); false)
313 | Ast0.CONTEXT
(mc
) ->
314 let (text
,tinfo1
,tinfo2
) = !mc
in
315 (match text
with Ast.NOTHING
-> false | _
-> true)
317 not
(contains_only_minus
.VT0.combiner_rec_statement s
) (*&&
318 (left_statement s) or (right_statement s)*)
319 | _
-> failwith
"unexpected plus code"
321 (* why do we need this; MINUS should mean the same thing *)
322 and contains_only_minus
=
323 let bind x y
= x
&& y
in
324 let option_default = true in
325 let mcodekind = function
330 | Ast0.CONTEXT
(mc
) -> false
332 let mcode (_
,_
,_
,mc
,_
,_
) = mcodekind mc
in
334 let donothing r k e
= mcodekind (Ast0.get_mcodekind e
) && k e
in
337 match Ast0.unwrap e
with
338 Ast0.DOTS
([]) | Ast0.CIRCLES
([]) | Ast0.STARS
([]) -> true
341 let expression r k e
=
342 mcodekind (Ast0.get_mcodekind e
) &&
343 match Ast0.unwrap e
with
344 Ast0.DisjExpr
(starter
,expr_list
,mids
,ender
) ->
345 List.for_all r
.VT0.combiner_rec_expression expr_list
348 let declaration r k e
=
349 mcodekind (Ast0.get_mcodekind e
) &&
350 match Ast0.unwrap e
with
351 Ast0.DisjDecl
(starter
,decls
,mids
,ender
) ->
352 List.for_all r
.VT0.combiner_rec_declaration decls
356 mcodekind (Ast0.get_mcodekind e
) &&
357 match Ast0.unwrap e
with
358 Ast0.DisjType
(starter
,types
,mids
,ender
) ->
359 List.for_all r
.VT0.combiner_rec_typeC types
362 let statement r k e
=
363 mcodekind (Ast0.get_mcodekind e
) &&
364 match Ast0.unwrap e
with
365 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
366 List.for_all r
.VT0.combiner_rec_statement_dots statement_dots_list
369 let case_line r k e
=
370 mcodekind (Ast0.get_mcodekind e
) &&
371 match Ast0.unwrap e
with
372 Ast0.DisjCase
(starter
,case_list
,mids
,ender
) ->
373 List.for_all r
.VT0.combiner_rec_case_line case_list
376 V0.flat_combiner
bind option_default
377 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
378 dots dots dots dots dots dots
379 donothing expression typeC donothing donothing declaration
380 statement case_line donothing
383 (* needs a special case when there is a Disj or an empty DOTS *)
384 (* ---------------------------------------------------------------------- *)
389 if (acpi_device_dir(device))
391 remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
392 + acpi_device_dir(device) = NULL;
395 The last two + lines get associated with the end of the if, not with the
396 branch, so the braces get added in oddly.
399 let add_braces orig_s
=
401 (Iso_pattern.rebuild_mcode None
).VT0.rebuilder_rec_statement orig_s
in
403 match Ast0.get_mcodekind
s with
405 let (text
,tinfo
) = !mc
in
406 Ast0.MINUS
(ref([Ast.mkToken
"{"]::text
@[[Ast.mkToken
"}"]],tinfo
))
407 | Ast0.CONTEXT
(mc
) ->
408 let (text
,tinfo1
,tinfo2
) = !mc
in
410 (* this is going to be a mess if we allow it to be iterable...
411 there would be one level of braces for every added things.
412 need to come up with something better, or just add {} in the
416 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,[[Ast.mkToken
"}"]],
418 | Ast.AFTER
(aft
,_
) ->
419 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],aft
@[[Ast.mkToken
"}"]],
421 | Ast.BEFOREAFTER
(bef
,aft
,_
) ->
422 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,aft
@[[Ast.mkToken
"}"]],
425 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],[[Ast.mkToken
"}"]],
427 Ast0.CONTEXT
(ref(new_text,tinfo1
,tinfo2
))
429 let (text
,tinfo1
,tinfo2
) = !mc
in
433 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,[[Ast.mkToken
"}"]],
435 | Ast.AFTER
(aft
,_
) ->
436 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],aft
@[[Ast.mkToken
"}"]],
438 | Ast.BEFOREAFTER
(bef
,aft
,_
) ->
439 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,aft
@[[Ast.mkToken
"}"]],
442 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],[[Ast.mkToken
"}"]],
444 Ast0.MIXED
(ref(new_text,tinfo1
,tinfo2
))
445 | _
-> failwith
"unexpected plus code" in
446 Ast0.set_mcodekind
s new_mcodekind;
447 Compute_lines.compute_statement_lines
true s
449 (* ---------------------------------------------------------------------- *)
452 match Ast0.unwrap x
with
453 Ast0.Dots
(_
,_
) | Ast0.Circles
(_
,_
) | Ast0.Stars
(_
,_
)
454 | Ast0.Nest
(_
,_
,_
,_
,_
) -> true
458 match Ast0.get_mcodekind
s with
459 Ast0.MINUS
(_
) -> true
462 let rec unchanged_minus s =
463 match Ast0.get_mcodekind
s with
464 Ast0.MINUS
(mc
) -> (match !mc
with ([],_
) -> true | _
-> false)
467 let rec do_branch s =
470 Ast0.set_dots_bef_aft
s (Ast0.DroppingBetweenDots
(add_braces s))
472 match Ast0.unwrap
s with
473 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
477 match Ast0.unwrap
s with
479 Ast0.rewrap
s (Ast0.DOTS
([do_branch s]))
481 | _
-> failwith
"not supported")
482 statement_dots_list
in
483 Ast0.rewrap
s (Ast0.Disj
(starter
,stmts,mids
,ender
))
486 let rec statement dots_before dots_after
s =
488 if dots_before
&& dots_after
492 (let with_braces = add_braces s in
493 Ast0.set_dots_bef_aft
s (Ast0.DroppingBetweenDots
(with_braces)))
494 else if adding_something s
496 (let with_braces = add_braces s in
497 Ast0.set_dots_bef_aft
s (Ast0.AddingBetweenDots
(with_braces)))
501 match Ast0.unwrap
s with
502 Ast0.FunDecl
(x
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
503 (* true for close brace, because that represents any way we can
504 exit the function, which is not necessarily followed by an explicit
507 (Ast0.FunDecl
(x
,fninfo
,name
,lp
,params
,rp
,lbrace
,
508 statement_dots
false true body
,
510 | Ast0.Decl
(_
,_
) -> s
511 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
513 (Ast0.Seq
(lbrace
,statement_dots
false false body
,rbrace
))
514 | Ast0.ExprStatement
(exp
,sem
) -> do_one s
515 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,x
) ->
518 (Ast0.IfThen
(iff
,lp
,exp
,rp
,statement false false branch1
,x
)))
519 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,x
) ->
524 statement false false branch1
,els
,
525 statement false false branch2
,x
)))
526 | Ast0.While
(whl
,lp
,exp
,rp
,body
,x
) ->
529 (Ast0.While
(whl
,lp
,exp
,rp
,statement false false body
,x
)))
530 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) ->
533 (Ast0.Do
(d
,statement false false body
,whl
,lp
,exp
,rp
,sem
)))
534 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,x
) ->
537 (Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,
538 statement false false body
,x
)))
539 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,x
) ->
542 (Ast0.Iterator
(nm
,lp
,args
,rp
,statement false false body
,x
)))
543 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
546 (Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,
549 (List.map
case_line (Ast0.undots cases
))),
551 | Ast0.Break
(br
,sem
) -> do_one s
552 | Ast0.Continue
(cont
,sem
) -> do_one s
553 | Ast0.Label
(l
,dd
) -> do_one s
554 | Ast0.Goto
(goto
,l
,sem
) -> do_one s
555 | Ast0.Return
(ret
,sem
) -> do_one s
556 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> do_one s
557 | Ast0.MetaStmt
(name
,_
) -> do_one s
558 | Ast0.MetaStmtList
(name
,_
) -> do_one s
559 | Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
562 List.map
(statement_dots dots_before dots_after
)
565 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
568 (starter
,statement_dots
true true stmt_dots
,ender
,whencode
,multi
))
570 | Ast0.TopExp
(exp
) -> s
572 | Ast0.TopInit
(init
) -> s
573 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> s
574 | Ast0.Include
(inc
,string) -> s (* doesn't affect the need for braces *)
575 | Ast0.Define
(def
,id
,params
,body
) -> s (* same as include *)
578 (Ast0.OptStm
(statement dots_before dots_after re
))
579 | Ast0.UniqueStm
(re
) ->
581 (Ast0.UniqueStm
(statement dots_before dots_after re
))
585 (match Ast0.unwrap c
with
586 Ast0.Default
(def
,colon
,code
) ->
587 Ast0.Default
(def
,colon
,statement_dots
false false code
)
588 | Ast0.Case
(case
,exp
,colon
,code
) ->
589 Ast0.Case
(case
,exp
,colon
,statement_dots
false false code
)
590 | Ast0.DisjCase
(starter
,case_lines
,mids
,ender
) ->
591 Ast0.DisjCase
(starter
,List.map
case_line case_lines
,mids
,ender
)
592 | Ast0.OptCase
(case
) -> Ast0.OptCase
(case_line c
))
594 and do_statement_dots dots_before dots_after
= function
596 | [x
] -> [statement dots_before dots_after x
]
597 | dots::rest
when is_dots dots ->
598 dots::(do_statement_dots
true dots_after rest
)
599 | x
::(dots::_
as rest
) when is_dots dots ->
600 (statement dots_before
true x
)::
601 do_statement_dots
false dots_after rest
603 (statement dots_before
false x
)::
604 do_statement_dots
false dots_after rest
606 and statement_dots dots_before dots_after d
=
608 (match Ast0.unwrap d
with
610 Ast0.DOTS
(do_statement_dots dots_before dots_after l
)
612 Ast0.CIRCLES
(do_statement_dots dots_before dots_after l
)
614 Ast0.STARS
(do_statement_dots dots_before dots_after l
))
618 (match Ast0.unwrap t
with
619 Ast0.DECL
(stmt_dots
) -> Ast0.DECL
(statement true true stmt_dots
)
620 | Ast0.CODE
(stmt_dots
) -> Ast0.CODE
(statement_dots
true true stmt_dots
)
623 let single_statement l
=
624 if !Flag_parsing_cocci.sgrep_mode
then l
else List.map
top_level l