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