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 (* Find a directive or comment at the end of a statement. Things with aft
28 given None, because they can accomodate their own directives or comments *)
30 module Ast0
= Ast0_cocci
31 module Ast
= Ast_cocci
32 module V0
= Visitor_ast0
33 module VT0
= Visitor_ast0_types
35 let call_right processor data s cont
=
36 match processor data
with
38 | Some
(pragmas
,data
) -> Some
(pragmas
,Ast0.rewrap s
(cont data
))
40 let left_mcode (a
,b
,info
,mcodekind
,d
,e
) =
41 match (info
.Ast0.strings_before
,mcodekind
) with
42 ([],_
) | (_
,Ast0.PLUS _
) -> None
43 | (l
,_
) -> Some
(l
,(a
,b
,{info
with Ast0.strings_before
= []},mcodekind
,d
,e
))
45 let right_mcode (a
,b
,info
,mcodekind
,d
,e
) =
46 match (info
.Ast0.strings_after
,mcodekind
) with
47 ([],_
) | (_
,Ast0.PLUS _
) -> None
48 | (l
,_
) -> Some
(l
,(a
,b
,{info
with Ast0.strings_after
= []},mcodekind
,d
,e
))
50 let update_before pragmas
(info
,x
) =
51 ({info
with Ast0.strings_before
= pragmas
@ info
.Ast0.strings_before
},
52 Ast0.PLUS
Ast.ONE
) (* not sure what the arg should be... one seems safe *)
54 let update_after pragmas
(info
,x
) =
55 ({info
with Ast0.strings_after
= info
.Ast0.strings_after
@ pragmas
},
56 Ast0.PLUS
Ast.ONE
) (* not sure what the arg should be... one seems safe *)
58 let rec right_decl d
=
59 match Ast0.unwrap d
with
60 Ast0.MetaDecl
(name
,pure
) ->
61 call_right right_mcode name d
62 (function name
-> Ast0.MetaDecl
(name
,pure
))
63 | Ast0.MetaField
(name
,pure
) ->
64 call_right right_mcode name d
65 (function name
-> Ast0.MetaField
(name
,pure
))
66 | Ast0.MetaFieldList
(name
,lenname
,pure
) ->
67 call_right right_mcode name d
68 (function name
-> Ast0.MetaFieldList
(name
,lenname
,pure
))
69 | Ast0.AsDecl
(decl
,asdecl
) -> failwith
"not possible"
70 | Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
) ->
71 call_right right_mcode sem d
72 (function sem
-> Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
))
73 | Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
) ->
74 call_right right_mcode sem d
75 (function sem
-> Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
))
76 | Ast0.UnInit
(Some stg
,ty
,id
,sem
) ->
77 call_right right_mcode sem d
78 (function sem
-> Ast0.UnInit
(Some stg
,ty
,id
,sem
))
79 | Ast0.UnInit
(None
,ty
,id
,sem
) ->
80 call_right right_mcode sem d
81 (function sem
-> Ast0.UnInit
(None
,ty
,id
,sem
))
82 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) ->
83 call_right right_mcode sem d
84 (function sem
-> Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
))
85 | Ast0.MacroDeclInit
(name
,lp
,args
,rp
,eq
,ini
,sem
) ->
86 call_right right_mcode sem d
87 (function sem
-> Ast0.MacroDeclInit
(name
,lp
,args
,rp
,eq
,ini
,sem
))
88 | Ast0.TyDecl
(ty
,sem
) ->
89 call_right right_mcode sem d
90 (function sem
-> Ast0.TyDecl
(ty
,sem
))
91 | Ast0.Typedef
(stg
,ty
,id
,sem
) ->
92 call_right right_mcode sem d
93 (function sem
-> Ast0.Typedef
(stg
,ty
,id
,sem
))
94 | Ast0.DisjDecl
(starter
,decls
,mids
,ender
) -> None
95 | Ast0.Ddots
(dots
,whencode
) -> None
96 | Ast0.OptDecl
(decl
) ->
97 call_right right_decl decl d
(function decl
-> Ast0.OptDecl
(decl
))
98 | Ast0.UniqueDecl
(decl
) ->
99 call_right right_decl decl d
(function decl
-> Ast0.UniqueDecl
(decl
))
101 let rec right_statement s
=
102 match Ast0.unwrap s
with
103 Ast0.FunDecl
(bef
,fi
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) -> None
104 | Ast0.Decl
(bef
,decl
) ->
105 call_right right_decl decl s
106 (function decl
-> Ast0.Decl
(bef
,decl
))
107 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
108 call_right right_mcode rbrace s
109 (function rbrace
-> Ast0.Seq
(lbrace
,body
,rbrace
))
110 | Ast0.ExprStatement
(exp
,sem
) ->
111 call_right right_mcode sem s
112 (function sem
-> Ast0.ExprStatement
(exp
,sem
))
113 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,aft
) -> None
114 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,aft
) -> None
115 | Ast0.While
(whl
,lp
,exp
,rp
,body
,aft
) -> None
116 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) ->
117 call_right right_mcode sem s
118 (function sem
-> Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
))
119 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,aft
) -> None
120 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,aft
) -> None
121 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
122 call_right right_mcode rb s
123 (function rb
-> Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
))
124 | Ast0.Break
(br
,sem
) ->
125 call_right right_mcode sem s
126 (function sem
-> Ast0.Break
(br
,sem
))
127 | Ast0.Continue
(cont
,sem
) ->
128 call_right right_mcode sem s
129 (function sem
-> Ast0.Continue
(cont
,sem
))
130 | Ast0.Label
(l
,dd
) ->
131 call_right right_mcode dd s
132 (function dd
-> Ast0.Label
(l
,dd
))
133 | Ast0.Goto
(goto
,l
,sem
) ->
134 call_right right_mcode sem s
135 (function sem
-> Ast0.Goto
(goto
,l
,sem
))
136 | Ast0.Return
(ret
,sem
) ->
137 call_right right_mcode sem s
138 (function sem
-> Ast0.Return
(ret
,sem
))
139 | Ast0.ReturnExpr
(ret
,exp
,sem
) ->
140 call_right right_mcode sem s
141 (function sem
-> Ast0.ReturnExpr
(ret
,exp
,sem
))
142 | Ast0.MetaStmt
(name
,pure
) ->
143 call_right right_mcode name s
144 (function name
-> Ast0.MetaStmt
(name
,pure
))
145 | Ast0.MetaStmtList
(name
,pure
) ->
146 call_right right_mcode name s
147 (function name
-> Ast0.MetaStmtList
(name
,pure
))
148 | Ast0.AsStmt
(stm
,asstm
) -> failwith
"not possible"
149 | Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) -> None
150 | Ast0.Nest
(starter
,stmt_dots
,ender
,whn
,multi
) -> None
151 (* the following are None, because they can't be adjacent to an aft node *)
152 | Ast0.Exp
(exp
) -> None
153 | Ast0.TopExp
(exp
) -> None
154 | Ast0.Ty
(ty
) -> None
155 | Ast0.TopInit
(init
) -> None
156 | Ast0.Dots
(d
,whn
) -> None
157 | Ast0.Circles
(d
,whn
) -> None
158 | Ast0.Stars
(d
,whn
) -> None
159 | Ast0.Include
(inc
,name
) ->
160 call_right right_mcode name s
161 (function name
-> Ast0.Include
(inc
,name
))
162 | Ast0.Undef
(def
,id
) ->
163 (* nothing available for ident, and not sure code can appear
166 | Ast0.Define
(def
,id
,params
,body
) ->
167 call_right right_statement_dots body s
168 (function body
-> Ast0.Define
(def
,id
,params
,body
))
170 call_right right_statement re s
(function re
-> Ast0.OptStm
(re
))
171 | Ast0.UniqueStm
(re
) ->
172 call_right right_statement re s
(function re
-> Ast0.UniqueStm
(re
))
174 and right_statement_dots sd
=
175 match Ast0.unwrap sd
with
176 Ast0.DOTS
([]) -> failwith
"empty statement dots"
178 call_right right_statement s sd
179 (function s
-> Ast0.DOTS
(List.rev
(s
::r
)))
180 | _
-> failwith
"circles and stars not supported"
183 match Ast0.unwrap t
with
184 Ast0.ConstVol
(cv
,ty
) ->
185 call_right left_mcode cv t
(function cv
-> Ast0.ConstVol
(cv
,ty
))
186 | Ast0.BaseType
(ty
,strings
) ->
188 [] -> failwith
"empty strings in type"
190 call_right left_mcode s t
(function s
-> Ast0.BaseType
(ty
,s
::r
)))
191 | Ast0.Signed
(sign
,ty
) ->
192 call_right left_mcode sign t
(function sign
-> Ast0.Signed
(sign
,ty
))
193 | Ast0.Pointer
(ty
,star
) ->
194 call_right left_ty ty t
(function ty
-> Ast0.Pointer
(ty
,star
))
195 | Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) ->
196 call_right left_ty ty t
197 (function ty
-> Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
))
198 | Ast0.FunctionType
(Some ty
,lp1
,params
,rp1
) ->
199 call_right left_ty ty t
200 (function ty
-> Ast0.FunctionType
(Some ty
,lp1
,params
,rp1
))
201 | Ast0.FunctionType
(None
,lp1
,params
,rp1
) ->
202 call_right left_mcode lp1 t
203 (function lp1
-> Ast0.FunctionType
(None
,lp1
,params
,rp1
))
204 | Ast0.Array
(ty
,lb
,size
,rb
) ->
205 call_right left_ty ty t
(function ty
-> Ast0.Array
(ty
,lb
,size
,rb
))
206 | Ast0.EnumName
(kind
,name
) ->
207 call_right left_mcode kind t
(function kind
-> Ast0.EnumName
(kind
,name
))
208 | Ast0.EnumDef
(ty
,lb
,ids
,rb
) ->
209 call_right left_ty ty t
210 (function ty
-> Ast0.EnumDef
(ty
,lb
,ids
,rb
))
211 | Ast0.StructUnionName
(kind
,name
) ->
212 call_right left_mcode kind t
213 (function kind
-> Ast0.StructUnionName
(kind
,name
))
214 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) ->
215 call_right left_ty ty t
216 (function ty
-> Ast0.StructUnionDef
(ty
,lb
,decls
,rb
))
217 | Ast0.TypeName
(name
) ->
218 call_right left_mcode name t
(function name
-> Ast0.TypeName
(name
))
219 | Ast0.MetaType
(name
,x
) ->
220 call_right left_mcode name t
(function name
-> Ast0.MetaType
(name
,x
))
221 | Ast0.AsType
(ty
,asty
) -> failwith
"not possible"
222 | Ast0.DisjType
(starter
,types
,mids
,ender
) -> None
223 | Ast0.OptType
(ty
) ->
224 call_right left_ty ty t
(function ty
-> Ast0.OptType
(ty
))
225 | Ast0.UniqueType
(ty
) ->
226 call_right left_ty ty t
(function ty
-> Ast0.UniqueType
(ty
))
228 let rec left_ident i
=
229 match Ast0.unwrap i
with
231 call_right left_mcode name i
(function name
-> Ast0.Id
(name
))
232 | Ast0.MetaId
(name
,a
,b
,c
) ->
233 call_right left_mcode name i
(function name
-> Ast0.MetaId
(name
,a
,b
,c
))
234 | Ast0.MetaFunc
(name
,a
,b
) ->
235 call_right left_mcode name i
(function name
-> Ast0.MetaFunc
(name
,a
,b
))
236 | Ast0.MetaLocalFunc
(name
,a
,b
) ->
237 call_right left_mcode name i
238 (function name
-> Ast0.MetaLocalFunc
(name
,a
,b
))
239 | Ast0.DisjId
(starter
,ids
,mids
,ender
) -> None
240 | Ast0.OptIdent
(id
) ->
241 call_right left_ident id i
(function id
-> Ast0.OptIdent
(id
))
242 | Ast0.UniqueIdent
(id
) ->
243 call_right left_ident id i
(function id
-> Ast0.UniqueIdent
(id
))
245 let left_fundecl name fninfo
=
246 let fncall_right processor data cont
=
247 match processor data
with
249 | Some
(pragmas
,data
) -> Some
(pragmas
,cont data
,name
) in
252 (match left_ident name
with
254 | Some
(pragmas
,name
) -> Some
(pragmas
,fninfo
,name
))
255 | (Ast0.FStorage sto
)::x
->
256 fncall_right left_mcode sto
(function sto
-> (Ast0.FStorage sto
)::x
)
257 | (Ast0.FType ty
)::x
->
258 fncall_right left_ty ty
(function ty
-> (Ast0.FType ty
)::x
)
259 | (Ast0.FInline inl
)::x
->
260 fncall_right left_mcode inl
(function inl
-> (Ast0.FInline inl
)::x
)
261 | (Ast0.FAttr atr
)::x
->
262 fncall_right left_mcode atr
(function atr
-> (Ast0.FAttr atr
)::x
)
264 let rec left_decl decl
=
265 match Ast0.unwrap decl
with
266 Ast0.MetaDecl
(name
,pure
) ->
267 call_right right_mcode name decl
268 (function name
-> Ast0.MetaDecl
(name
,pure
))
269 | Ast0.MetaField
(name
,pure
) ->
270 call_right right_mcode name decl
271 (function name
-> Ast0.MetaField
(name
,pure
))
272 | Ast0.MetaFieldList
(name
,lenname
,pure
) ->
273 call_right right_mcode name decl
274 (function name
-> Ast0.MetaFieldList
(name
,lenname
,pure
))
275 | Ast0.AsDecl
(decl
,asdecl
) -> failwith
"not possible"
276 | Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
) ->
277 call_right left_mcode stg decl
278 (function stg
-> Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
))
279 | Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
) ->
280 call_right left_ty ty decl
281 (function ty
-> Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
))
282 | Ast0.UnInit
(Some stg
,ty
,id
,sem
) ->
283 call_right left_mcode stg decl
284 (function stg
-> Ast0.UnInit
(Some stg
,ty
,id
,sem
))
285 | Ast0.UnInit
(None
,ty
,id
,sem
) ->
286 call_right left_ty ty decl
287 (function ty
-> Ast0.UnInit
(None
,ty
,id
,sem
))
288 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) ->
289 call_right left_ident name decl
290 (function name
-> Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
))
291 | Ast0.MacroDeclInit
(name
,lp
,args
,rp
,eq
,ini
,sem
) ->
292 call_right left_ident name decl
293 (function name
-> Ast0.MacroDeclInit
(name
,lp
,args
,rp
,eq
,ini
,sem
))
294 | Ast0.TyDecl
(ty
,sem
) ->
295 call_right left_ty ty decl
(function ty
-> Ast0.TyDecl
(ty
,sem
))
296 | Ast0.Typedef
(stg
,ty
,id
,sem
) ->
297 call_right left_mcode stg decl
298 (function stg
-> Ast0.Typedef
(stg
,ty
,id
,sem
))
299 | Ast0.DisjDecl
(starter
,decls
,mids
,ender
) -> None
300 | Ast0.Ddots
(dots
,whencode
) -> None
302 call_right left_decl d decl
(function decl
-> Ast0.OptDecl
(decl
))
303 | Ast0.UniqueDecl
(d
) ->
304 call_right left_decl d decl
(function decl
-> Ast0.UniqueDecl
(decl
))
307 let statement r k s
=
310 (match Ast0.unwrap
s with
311 Ast0.FunDecl
(bef
,fi
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
312 (match left_fundecl name fi
with
313 None
-> Ast0.unwrap
s
314 | Some
(pragmas
,fi
,name
) ->
316 (update_after pragmas bef
,
317 fi
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
))
318 | Ast0.Decl
(bef
,decl
) ->
319 (match left_decl decl
with
320 None
-> Ast0.unwrap
s
321 | Some
(pragmas
,decl
) ->
322 Ast0.Decl
(update_after pragmas bef
,decl
))
323 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,aft
) ->
324 (match right_statement branch1
with
325 None
-> Ast0.unwrap
s
326 | Some
(pragmas
,branch1
) ->
328 (iff
,lp
,exp
,rp
,branch1
,update_before pragmas aft
))
329 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,aft
) ->
330 (match right_statement branch2
with
331 None
-> Ast0.unwrap
s
332 | Some
(pragmas
,branch2
) ->
334 (iff
,lp
,exp
,rp
,branch1
,els
,branch2
,
335 update_before pragmas aft
))
336 | Ast0.While
(whl
,lp
,exp
,rp
,body
,aft
) ->
337 (match right_statement body
with
338 None
-> Ast0.unwrap
s
339 | Some
(pragmas
,body
) ->
340 Ast0.While
(whl
,lp
,exp
,rp
,body
,update_before pragmas aft
))
341 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,aft
) ->
342 (match right_statement body
with
343 None
-> Ast0.unwrap
s
344 | Some
(pragmas
,body
) ->
346 (fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,
347 update_before pragmas aft
))
348 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,aft
) ->
349 (match right_statement body
with
350 None
-> Ast0.unwrap
s
351 | Some
(pragmas
,body
) ->
352 Ast0.Iterator
(nm
,lp
,args
,rp
,body
,update_before pragmas aft
))
353 | _
-> Ast0.unwrap
s) in
355 let res = V0.rebuilder
356 {V0.rebuilder_functions
with VT0.rebuilder_stmtfn
= statement} in
358 List.map
res.VT0.rebuilder_rec_top_level