2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
5 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
6 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
7 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
8 * This file is part of Coccinelle.
10 * Coccinelle is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, according to version 2 of the License.
14 * Coccinelle is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
27 #
0 "./single_statement.ml"
29 * Copyright 2012, INRIA
30 * Julia Lawall, Gilles Muller
31 * Copyright 2010-2011, INRIA, University of Copenhagen
32 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
33 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
34 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
35 * This file is part of Coccinelle.
37 * Coccinelle is free software: you can redistribute it and/or modify
38 * it under the terms of the GNU General Public License as published by
39 * the Free Software Foundation, according to version 2 of the License.
41 * Coccinelle is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 * GNU General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
49 * The authors reserve the right to distribute this or future versions of
50 * Coccinelle under other licenses.
54 #
0 "./single_statement.ml"
55 (* detect statements that are between dots in the minus code, because they
56 may need a special treatment if they are if branches *)
58 module Ast0
= Ast0_cocci
59 module Ast
= Ast_cocci
60 module V0
= Visitor_ast0
61 module VT0
= Visitor_ast0_types
63 (* --------------------------------------------------------------------- *)
64 (* --------------------------------------------------------------------- *)
68 match Ast0.undots l
with
73 match List.rev
(Ast0.undots l
) with
77 let modif_before_mcode mc
=
78 match Ast0.get_mcode_mcodekind mc
with
79 Ast0.MINUS mc
-> true (*conservative; don't want to hunt right for + code*)
80 | Ast0.PLUS _
-> failwith
"not possible"
83 (Ast.BEFORE _
,_
,_
) -> true
84 | (Ast.BEFOREAFTER _
,_
,_
) -> true
86 | Ast0.MIXED mc
-> true (* don't think mcode can be mixed *)
88 let modif_after_mcodekind = function
89 Ast0.MINUS mc
-> true (*conservative; don't want to hunt right for + code*)
90 | Ast0.PLUS _
-> failwith
"not possible"
93 (Ast.AFTER _
,_
,_
) -> true
94 | (Ast.BEFOREAFTER _
,_
,_
) -> true
96 | Ast0.MIXED mc
-> true (* don't think mcode can be mixed *)
98 let modif_after_mcode mc
= modif_after_mcodekind (Ast0.get_mcode_mcodekind mc
)
104 Ast.StatementTag
(_
) | Ast.StmtDotsTag
(_
)
105 | Ast.DeclarationTag
(_
) | Ast.DeclDotsTag
(_
) -> true | _
-> false))
108 match Ast0.get_mcodekind x
with
109 Ast0.PLUS _
-> failwith
"not possible"
112 (* do better for the common case of replacing a stmt by another one *)
113 ((Ast.REPLACEMENT
([[Ast.StatementTag
(s
)]],c
)) as old
,ti
) ->
114 (match Ast.unwrap s
with
115 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
116 | _
-> mc
:= (old
,ti
); false)
118 | Ast0.CONTEXT mc
| Ast0.MIXED mc
->
120 (Ast.BEFORE _
,_
,_
) -> true
121 | (Ast.BEFOREAFTER _
,_
,_
) -> true
125 match Ast0.get_mcodekind x
with
126 Ast0.PLUS _
-> failwith
"not possible"
129 (* do better for the common case of replacing a stmt by another one *)
130 ((Ast.REPLACEMENT
([[Ast.StatementTag
(s
)]],count
)) as old
,ti
) ->
131 (match Ast.unwrap s
with
132 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
133 | _
-> mc
:= (old
,ti
); false)
134 | (Ast.REPLACEMENT
(l
,_
),_
) when any_statements l
-> true
135 | (l
,ti
) -> mc
:= (l
,ti
); false)
136 | Ast0.CONTEXT mc
| Ast0.MIXED mc
->
138 (Ast.AFTER _
,_
,_
) -> true
139 | (Ast.BEFOREAFTER _
,_
,_
) -> true
143 let rec left_ident i
=
145 match Ast0.unwrap i
with
146 Ast0.Id
(name
) -> modif_before_mcode name
147 | Ast0.MetaId
(name
,_
,_
,_
) -> modif_before_mcode name
148 | Ast0.MetaFunc
(name
,_
,_
) -> modif_before_mcode name
149 | Ast0.MetaLocalFunc
(name
,_
,_
) -> modif_before_mcode name
150 | Ast0.DisjId
(_
,id_list
,_
,_
) -> List.exists
left_ident id_list
151 | Ast0.OptIdent
(id
) -> left_ident id
152 | Ast0.UniqueIdent
(id
) -> left_ident id
153 | Ast0.AsIdent _
-> failwith
"not possible"
155 let rec right_ident i
=
157 match Ast0.unwrap i
with
158 Ast0.Id
(name
) -> modif_after_mcode name
159 | Ast0.MetaId
(name
,_
,_
,_
) -> modif_after_mcode name
160 | Ast0.MetaFunc
(name
,_
,_
) -> modif_after_mcode name
161 | Ast0.MetaLocalFunc
(name
,_
,_
) -> modif_after_mcode name
162 | Ast0.DisjId
(_
,id_list
,_
,_
) -> List.exists
right_ident id_list
163 | Ast0.OptIdent
(id
) -> right_ident id
164 | Ast0.UniqueIdent
(id
) -> right_ident id
165 | Ast0.AsIdent _
-> failwith
"not possible"
167 (* --------------------------------------------------------------------- *)
170 let rec left_expression e
=
172 match Ast0.unwrap e
with
173 Ast0.Ident
(id
) -> left_ident id
174 | Ast0.Constant
(const
) -> modif_before_mcode const
175 | Ast0.FunCall
(fn
,lp
,args
,rp
) -> left_expression fn
176 | Ast0.Assignment
(left
,op
,right
,_
) -> left_expression left
177 | Ast0.Sequence
(left
,op
,right
) -> left_expression left
178 | Ast0.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) -> left_expression exp1
179 | Ast0.Postfix
(exp
,op
) -> left_expression exp
180 | Ast0.Infix
(exp
,op
) -> modif_before_mcode op
181 | Ast0.Unary
(exp
,op
) -> modif_before_mcode op
182 | Ast0.Binary
(left
,op
,right
) -> left_expression left
183 | Ast0.Nested
(left
,op
,right
) -> left_expression left
184 | Ast0.Paren
(lp
,exp
,rp
) -> modif_before_mcode lp
185 | Ast0.ArrayAccess
(exp1
,lb
,exp2
,rb
) -> left_expression exp1
186 | Ast0.RecordAccess
(exp
,pt
,field
) -> left_expression exp
187 | Ast0.RecordPtAccess
(exp
,ar
,field
) -> left_expression exp
188 | Ast0.Cast
(lp
,ty
,rp
,exp
) -> modif_before_mcode lp
189 | Ast0.SizeOfExpr
(szf
,exp
) -> modif_before_mcode szf
190 | Ast0.SizeOfType
(szf
,lp
,ty
,rp
) -> modif_before_mcode szf
191 | Ast0.TypeExp
(ty
) -> left_typeC ty
192 | Ast0.Constructor
(lp
,ty
,rp
,init
) -> modif_before_mcode lp
193 | Ast0.MetaErr
(name
,_
,_
) -> modif_before_mcode name
194 | Ast0.MetaExpr
(name
,_
,ty
,_
,_
) -> modif_before_mcode name
195 | Ast0.MetaExprList
(name
,_
,_
) -> modif_before_mcode name
196 | Ast0.EComma
(cm
) -> modif_before_mcode cm
197 | Ast0.DisjExpr
(_
,exp_list
,_
,_
) -> List.exists
left_expression exp_list
198 | Ast0.NestExpr
(starter
,expr_dots
,ender
,_
,multi
) ->
199 left_dots left_expression expr_dots
200 | Ast0.Edots
(dots
,_
) | Ast0.Ecircles
(dots
,_
) | Ast0.Estars
(dots
,_
) -> false
201 | Ast0.OptExp
(exp
) -> left_expression exp
202 | Ast0.UniqueExp
(exp
) -> left_expression exp
203 | Ast0.AsExpr _
-> failwith
"not possible"
205 (* --------------------------------------------------------------------- *)
210 match Ast0.unwrap t
with
211 Ast0.ConstVol
(cv
,ty
) -> modif_before_mcode cv
212 | Ast0.BaseType
(ty
,strings
) -> modif_before_mcode (List.hd strings
)
213 | Ast0.Signed
(sgn
,ty
) -> modif_before_mcode sgn
214 | Ast0.Pointer
(ty
,star
) -> left_typeC ty
215 | Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) -> left_typeC ty
216 | Ast0.FunctionType
(Some ty
,lp1
,params
,rp1
) -> left_typeC ty
217 | Ast0.FunctionType
(None
,lp1
,params
,rp1
) -> modif_before_mcode lp1
218 | Ast0.Array
(ty
,lb
,size
,rb
) -> left_typeC ty
219 | Ast0.EnumName
(kind
,name
) -> modif_before_mcode kind
220 | Ast0.EnumDef
(ty
,lb
,ids
,rb
) -> left_typeC ty
221 | Ast0.StructUnionName
(kind
,name
) -> modif_before_mcode kind
222 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) -> left_typeC ty
223 | Ast0.TypeName
(name
) -> modif_before_mcode name
224 | Ast0.MetaType
(name
,_
) -> modif_before_mcode name
225 | Ast0.DisjType
(lp
,types
,mids
,rp
) -> List.exists left_typeC types
226 | Ast0.OptType
(ty
) -> left_typeC ty
227 | Ast0.UniqueType
(ty
) -> left_typeC ty
228 | Ast0.AsType _
-> failwith
"not possible"
231 (* --------------------------------------------------------------------- *)
232 (* Variable declaration *)
233 (* Even if the Cocci program specifies a list of declarations, they are
234 split out into multiple declarations of a single variable each. *)
236 and left_declaration d
=
238 match Ast0.unwrap d
with
239 Ast0.MetaDecl
(name
,_
) | Ast0.MetaField
(name
,_
)
240 | Ast0.MetaFieldList
(name
,_
,_
) ->
241 modif_before_mcode name
242 | Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
) -> modif_before_mcode stg
243 | Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
) -> left_typeC ty
244 | Ast0.UnInit
(Some stg
,ty
,id
,sem
) -> modif_before_mcode stg
245 | Ast0.UnInit
(None
,ty
,id
,sem
) -> left_typeC ty
246 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) -> left_ident name
247 | Ast0.MacroDeclInit
(name
,lp
,args
,rp
,eq
,ini
,sem
) -> left_ident name
248 | Ast0.TyDecl
(ty
,sem
) -> left_typeC ty
249 | Ast0.Typedef
(stg
,ty
,id
,sem
) -> modif_before_mcode stg
250 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> List.exists left_declaration decls
251 | Ast0.Ddots
(dots
,_
) -> false
252 | Ast0.OptDecl
(decl
) -> left_declaration decl
253 | Ast0.UniqueDecl
(decl
) -> left_declaration decl
254 | Ast0.AsDecl _
-> failwith
"not possible"
256 and right_declaration d
=
258 match Ast0.unwrap d
with
259 Ast0.MetaDecl
(name
,_
) | Ast0.MetaField
(name
,_
)
260 | Ast0.MetaFieldList
(name
,_
,_
) ->
261 modif_before_mcode name
262 | Ast0.Init
(_
,ty
,id
,eq
,ini
,sem
) -> modif_after_mcode sem
263 | Ast0.UnInit
(_
,ty
,id
,sem
) -> modif_after_mcode sem
264 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) -> modif_after_mcode sem
265 | Ast0.MacroDeclInit
(name
,lp
,args
,rp
,eq
,ini
,sem
) -> modif_after_mcode sem
266 | Ast0.TyDecl
(ty
,sem
) -> modif_after_mcode sem
267 | Ast0.Typedef
(stg
,ty
,id
,sem
) -> modif_after_mcode sem
268 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> List.exists right_declaration decls
269 | Ast0.Ddots
(dots
,_
) -> false
270 | Ast0.OptDecl
(decl
) -> right_declaration decl
271 | Ast0.UniqueDecl
(decl
) -> right_declaration decl
272 | Ast0.AsDecl _
-> failwith
"not possible"
274 (* --------------------------------------------------------------------- *)
277 and left_statement s
=
279 match Ast0.unwrap s
with
280 Ast0.FunDecl
(_
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
281 (* irrelevant *) false
282 | Ast0.Decl
(_
,decl
) -> left_declaration decl
283 | Ast0.Seq
(lbrace
,body
,rbrace
) -> modif_before_mcode lbrace
284 | Ast0.ExprStatement
(Some exp
,sem
) -> left_expression exp
285 | Ast0.ExprStatement
(None
,sem
) -> modif_before_mcode sem
286 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,(info
,aft
)) -> modif_before_mcode iff
287 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,(info
,aft
)) ->
288 modif_before_mcode iff
289 | Ast0.While
(whl
,lp
,exp
,rp
,body
,(info
,aft
)) -> modif_before_mcode whl
290 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) -> modif_before_mcode d
291 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,(info
,aft
)) ->
292 modif_before_mcode fr
293 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,(info
,aft
)) -> left_ident nm
294 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
295 modif_before_mcode switch
296 | Ast0.Break
(br
,sem
) -> modif_before_mcode br
297 | Ast0.Continue
(cont
,sem
) -> modif_before_mcode cont
298 | Ast0.Label
(l
,dd
) -> left_ident l
299 | Ast0.Goto
(goto
,l
,sem
) -> modif_before_mcode goto
300 | Ast0.Return
(ret
,sem
) -> modif_before_mcode ret
301 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> modif_before_mcode ret
302 | Ast0.MetaStmt
(name
,pure
) -> modif_before_mcode name
303 | Ast0.MetaStmtList
(name
,_
) -> modif_before_mcode name
304 | Ast0.Disj
(_
,statement_dots_list
,_
,_
) ->
305 List.exists
(left_dots left_statement
) statement_dots_list
306 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
307 left_dots left_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 *)
311 | Ast0.TopInit
(init
) -> false (* can only be replaced by an init *)
312 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> false
313 | Ast0.Include
(inc
,s
) -> modif_before_mcode inc
314 | Ast0.Undef
(def
,id
) -> modif_before_mcode def
315 | Ast0.Define
(def
,id
,params
,body
) -> modif_before_mcode def
316 | Ast0.OptStm
(re
) -> left_statement re
317 | Ast0.UniqueStm
(re
) -> left_statement re
318 | Ast0.AsStmt _
-> failwith
"not possible"
320 and right_statement s
=
322 match Ast0.unwrap s
with
323 Ast0.FunDecl
(_
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
324 (* irrelevant *) false
325 | Ast0.Decl
(_
,decl
) -> right_declaration decl
326 | Ast0.Seq
(lbrace
,body
,rbrace
) -> modif_after_mcode rbrace
327 | Ast0.ExprStatement
(exp
,sem
) -> modif_after_mcode sem
328 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,(info
,aft
)) -> modif_after_mcodekind aft
329 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,(info
,aft
)) ->
330 modif_after_mcodekind aft
331 | Ast0.While
(whl
,lp
,exp
,rp
,body
,(info
,aft
)) -> modif_after_mcodekind aft
332 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) -> modif_after_mcode sem
333 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,(info
,aft
)) ->
334 modif_after_mcodekind aft
335 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,(info
,aft
)) ->
336 modif_after_mcodekind aft
337 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) -> modif_after_mcode rb
338 | Ast0.Break
(br
,sem
) -> modif_after_mcode sem
339 | Ast0.Continue
(cont
,sem
) -> modif_after_mcode sem
340 | Ast0.Label
(l
,dd
) -> modif_after_mcode dd
341 | Ast0.Goto
(goto
,l
,sem
) -> modif_after_mcode sem
342 | Ast0.Return
(ret
,sem
) -> modif_after_mcode sem
343 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> modif_after_mcode sem
344 | Ast0.MetaStmt
(name
,pure
) -> modif_after_mcode name
345 | Ast0.MetaStmtList
(name
,_
) -> modif_after_mcode name
346 | Ast0.Disj
(_
,statement_dots_list
,_
,_
) ->
347 List.exists
(right_dots right_statement
) statement_dots_list
348 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
349 right_dots right_statement stmt_dots
350 | Ast0.Exp
(exp
) -> false (* can only be replaced by an expression *)
351 | Ast0.TopExp
(exp
) -> false (* as above *)
352 | Ast0.Ty
(ty
) -> false (* can only be replaced by a type *)
353 | Ast0.TopInit
(init
) -> false (* can only be replaced by an init *)
354 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> false
355 | Ast0.Include
(inc
,s
) -> modif_after_mcode s
356 | Ast0.Undef
(def
,id
) -> right_ident id
357 | Ast0.Define
(def
,id
,params
,body
) -> right_dots right_statement body
358 | Ast0.OptStm
(re
) -> right_statement re
359 | Ast0.UniqueStm
(re
) -> right_statement re
360 | Ast0.AsStmt _
-> failwith
"not possible"
362 (* --------------------------------------------------------------------- *)
365 (* A very coarse approximation. We would really only like to return true
366 if a new statement is added. For this it would be best to correlate with the
367 plus slice. Or at least be sure that the new stuff is on the far left or
370 let rec adding_something s
=
371 match Ast0.get_mcodekind s
with
374 (* do better for the common case of replacing a stmt by another one *)
375 ((Ast.REPLACEMENT
([[Ast.StatementTag
(s
)]],c
)) as old
,ti
) ->
376 (match Ast.unwrap s
with
377 Ast.IfThen
(_
,_
,_
) -> true (* potentially dangerous *)
378 | _
-> mc
:= (old
,ti
); false)
380 | Ast0.CONTEXT
(mc
) ->
381 let (text
,tinfo1
,tinfo2
) = !mc
in
382 (match text
with Ast.NOTHING
-> false | _
-> true)
384 not
(contains_only_minus
.VT0.combiner_rec_statement s
) (*&&
385 (left_statement s) or (right_statement s)*)
386 | _
-> failwith
"unexpected plus code"
388 (* why do we need this; MINUS should mean the same thing *)
389 and contains_only_minus
=
390 let bind x y
= x
&& y
in
391 let option_default = true in
392 let mcodekind = function
395 (Ast.NOREPLACEMENT
,_
) -> true
397 | Ast0.CONTEXT
(mc
) -> false
399 let mcode (_
,_
,_
,mc
,_
,_
) = mcodekind mc
in
401 let donothing r k e
= mcodekind (Ast0.get_mcodekind e
) && k e
in
404 match Ast0.unwrap e
with
405 Ast0.DOTS
([]) | Ast0.CIRCLES
([]) | Ast0.STARS
([]) -> true
408 let identifier r k e
=
409 mcodekind (Ast0.get_mcodekind e
) &&
410 match Ast0.unwrap e
with
411 Ast0.DisjId
(starter
,id_list
,mids
,ender
) ->
412 List.for_all r
.VT0.combiner_rec_ident id_list
415 let expression r k e
=
416 mcodekind (Ast0.get_mcodekind e
) &&
417 match Ast0.unwrap e
with
418 Ast0.DisjExpr
(starter
,expr_list
,mids
,ender
) ->
419 List.for_all r
.VT0.combiner_rec_expression expr_list
422 let declaration r k e
=
423 mcodekind (Ast0.get_mcodekind e
) &&
424 match Ast0.unwrap e
with
425 Ast0.DisjDecl
(starter
,decls
,mids
,ender
) ->
426 List.for_all r
.VT0.combiner_rec_declaration decls
430 mcodekind (Ast0.get_mcodekind e
) &&
431 match Ast0.unwrap e
with
432 Ast0.DisjType
(starter
,types
,mids
,ender
) ->
433 List.for_all r
.VT0.combiner_rec_typeC types
436 let statement r k e
=
437 mcodekind (Ast0.get_mcodekind e
) &&
438 match Ast0.unwrap e
with
439 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
440 List.for_all r
.VT0.combiner_rec_statement_dots statement_dots_list
443 let case_line r k e
=
444 mcodekind (Ast0.get_mcodekind e
) &&
445 match Ast0.unwrap e
with
446 Ast0.DisjCase
(starter
,case_list
,mids
,ender
) ->
447 List.for_all r
.VT0.combiner_rec_case_line case_list
450 V0.flat_combiner
bind option_default
451 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
452 dots dots dots dots dots dots
453 identifier expression typeC donothing donothing declaration
454 statement case_line donothing
457 (* needs a special case when there is a Disj or an empty DOTS *)
458 (* ---------------------------------------------------------------------- *)
463 if (acpi_device_dir(device))
465 remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
466 + acpi_device_dir(device) = NULL;
469 The last two + lines get associated with the end of the if, not with the
470 branch, so the braces get added in oddly.
473 let add_braces orig_s
=
475 (Iso_pattern.rebuild_mcode None
).VT0.rebuilder_rec_statement orig_s
in
477 match Ast0.get_mcodekind
s with
479 let (text
,tinfo
) = !mc
in
482 Ast.NOREPLACEMENT
-> [[Ast.mkToken
"{}"]]
483 | Ast.REPLACEMENT
(anythings
,Ast.ONE
) ->
484 [Ast.mkToken
"{"]::anythings
@[[Ast.mkToken
"}"]]
485 | Ast.REPLACEMENT
(anythings
,Ast.MANY
) ->
486 failwith
"++ not supported when braces must be added" in
487 Ast0.MINUS
(ref(Ast.REPLACEMENT
(inner_text,Ast.ONE
),tinfo
))
488 | Ast0.CONTEXT
(mc
) ->
489 let (text
,tinfo1
,tinfo2
) = !mc
in
491 (* this is going to be a mess if we allow it to be iterable...
492 there would be one level of braces for every added things.
493 need to come up with something better, or just add {} in the
497 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,[[Ast.mkToken
"}"]],
499 | Ast.AFTER
(aft
,_
) ->
500 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],aft
@[[Ast.mkToken
"}"]],
502 | Ast.BEFOREAFTER
(bef
,aft
,_
) ->
503 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,aft
@[[Ast.mkToken
"}"]],
506 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],[[Ast.mkToken
"}"]],
508 Ast0.CONTEXT
(ref(new_text,tinfo1
,tinfo2
))
510 let (text
,tinfo1
,tinfo2
) = !mc
in
514 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,[[Ast.mkToken
"}"]],
516 | Ast.AFTER
(aft
,_
) ->
517 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],aft
@[[Ast.mkToken
"}"]],
519 | Ast.BEFOREAFTER
(bef
,aft
,_
) ->
520 Ast.BEFOREAFTER
([Ast.mkToken
"{"]::bef
,aft
@[[Ast.mkToken
"}"]],
523 Ast.BEFOREAFTER
([[Ast.mkToken
"{"]],[[Ast.mkToken
"}"]],
525 Ast0.MIXED
(ref(new_text,tinfo1
,tinfo2
))
526 | _
-> failwith
"unexpected plus code" in
527 Ast0.set_mcodekind
s new_mcodekind;
528 Compute_lines.compute_statement_lines
true s
530 (* ---------------------------------------------------------------------- *)
533 match Ast0.unwrap x
with
534 Ast0.Dots
(_
,_
) | Ast0.Circles
(_
,_
) | Ast0.Stars
(_
,_
)
535 | Ast0.Nest
(_
,_
,_
,_
,_
) -> true
539 match Ast0.get_mcodekind
s with
540 Ast0.MINUS
(_
) -> true
543 let rec unchanged_minus s =
544 match Ast0.get_mcodekind
s with
546 (match !mc
with (Ast.NOREPLACEMENT
,_
) -> true | _
-> false)
549 let rec do_branch s =
552 Ast0.set_dots_bef_aft
s (Ast0.DroppingBetweenDots
(add_braces s))
554 match Ast0.unwrap
s with
555 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
559 match Ast0.unwrap
s with
561 Ast0.rewrap
s (Ast0.DOTS
([do_branch s]))
563 | _
-> failwith
"not supported")
564 statement_dots_list
in
565 Ast0.rewrap
s (Ast0.Disj
(starter
,stmts,mids
,ender
))
568 let rec statement dots_before dots_after
s =
570 if dots_before
&& dots_after
574 (let with_braces = add_braces s in
575 Ast0.set_dots_bef_aft
s (Ast0.DroppingBetweenDots
(with_braces)))
576 else if adding_something s
578 (let with_braces = add_braces s in
579 Ast0.set_dots_bef_aft
s (Ast0.AddingBetweenDots
(with_braces)))
583 match Ast0.unwrap
s with
584 Ast0.FunDecl
(x
,fninfo
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
585 (* true for close brace, because that represents any way we can
586 exit the function, which is not necessarily followed by an explicit
589 (Ast0.FunDecl
(x
,fninfo
,name
,lp
,params
,rp
,lbrace
,
590 statement_dots
false true body
,
592 | Ast0.Decl
(_
,_
) -> s
593 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
595 (Ast0.Seq
(lbrace
,statement_dots
false false body
,rbrace
))
596 | Ast0.ExprStatement
(exp
,sem
) -> do_one s
597 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,x
) ->
600 (Ast0.IfThen
(iff
,lp
,exp
,rp
,statement false false branch1
,x
)))
601 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,x
) ->
606 statement false false branch1
,els
,
607 statement false false branch2
,x
)))
608 | Ast0.While
(whl
,lp
,exp
,rp
,body
,x
) ->
611 (Ast0.While
(whl
,lp
,exp
,rp
,statement false false body
,x
)))
612 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) ->
615 (Ast0.Do
(d
,statement false false body
,whl
,lp
,exp
,rp
,sem
)))
616 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,x
) ->
619 (Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,
620 statement false false body
,x
)))
621 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,x
) ->
624 (Ast0.Iterator
(nm
,lp
,args
,rp
,statement false false body
,x
)))
625 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
628 (Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,
631 (List.map
case_line (Ast0.undots cases
))),
633 | Ast0.Break
(br
,sem
) -> do_one s
634 | Ast0.Continue
(cont
,sem
) -> do_one s
635 | Ast0.Label
(l
,dd
) -> do_one s
636 | Ast0.Goto
(goto
,l
,sem
) -> do_one s
637 | Ast0.Return
(ret
,sem
) -> do_one s
638 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> do_one s
639 | Ast0.MetaStmt
(name
,_
) -> do_one s
640 | Ast0.MetaStmtList
(name
,_
) -> do_one s
641 | Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
644 List.map
(statement_dots dots_before dots_after
)
647 | Ast0.Nest
(starter
,stmt_dots
,ender
,whencode
,multi
) ->
648 (match Ast0.get_mcode_mcodekind starter
with
649 Ast0.MINUS _
-> (* everything removed, like -... *) s
653 (starter
,statement_dots
true true stmt_dots
,ender
,
656 | Ast0.TopExp
(exp
) -> s
658 | Ast0.TopInit
(init
) -> s
659 | Ast0.Dots
(d
,whn
) | Ast0.Circles
(d
,whn
) | Ast0.Stars
(d
,whn
) -> s
660 | Ast0.Include
(inc
,string) -> s (* doesn't affect the need for braces *)
661 | Ast0.Undef
(def
,id
) -> s (* same as include *)
662 | Ast0.Define
(def
,id
,params
,body
) -> s (* same as include *)
665 (Ast0.OptStm
(statement dots_before dots_after re
))
666 | Ast0.UniqueStm
(re
) ->
668 (Ast0.UniqueStm
(statement dots_before dots_after re
))
669 | Ast0.AsStmt _
-> failwith
"not possible"
673 (match Ast0.unwrap c
with
674 Ast0.Default
(def
,colon
,code
) ->
675 Ast0.Default
(def
,colon
,statement_dots
false false code
)
676 | Ast0.Case
(case
,exp
,colon
,code
) ->
677 Ast0.Case
(case
,exp
,colon
,statement_dots
false false code
)
678 | Ast0.DisjCase
(starter
,case_lines
,mids
,ender
) ->
679 Ast0.DisjCase
(starter
,List.map
case_line case_lines
,mids
,ender
)
680 | Ast0.OptCase
(case
) -> Ast0.OptCase
(case_line c
))
682 and do_statement_dots dots_before dots_after
= function
684 | [x
] -> [statement dots_before dots_after x
]
685 | dots::rest
when is_dots dots ->
686 dots::(do_statement_dots
true dots_after rest
)
687 | x
::(dots::_
as rest
) when is_dots dots ->
688 (statement dots_before
true x
)::
689 do_statement_dots
false dots_after rest
691 (statement dots_before
false x
)::
692 do_statement_dots
false dots_after rest
694 and statement_dots dots_before dots_after d
=
696 (match Ast0.unwrap d
with
698 Ast0.DOTS
(do_statement_dots dots_before dots_after l
)
700 Ast0.CIRCLES
(do_statement_dots dots_before dots_after l
)
702 Ast0.STARS
(do_statement_dots dots_before dots_after l
))
706 (match Ast0.unwrap t
with
707 Ast0.NONDECL
(stmt_dots
) -> Ast0.NONDECL
(statement true true stmt_dots
)
708 | Ast0.CODE
(stmt_dots
) -> Ast0.CODE
(statement_dots
true true stmt_dots
)
711 let single_statement l
=
712 if !Flag_parsing_cocci.sgrep_mode
then l
else List.map
top_level l