2 * Copyright 2005-2010, 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.
24 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
25 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
26 * This file is part of Coccinelle.
28 * Coccinelle is free software: you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation, according to version 2 of the License.
32 * Coccinelle is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
40 * The authors reserve the right to distribute this or future versions of
41 * Coccinelle under other licenses.
45 (* Find a directive or comment at the end of a statement. Things with aft
46 given None, because they can accomodate their own directives or comments *)
48 module Ast0
= Ast0_cocci
49 module Ast
= Ast_cocci
50 module V0
= Visitor_ast0
51 module VT0
= Visitor_ast0_types
53 let call_right processor data s cont
=
54 match processor data
with
56 | Some
(pragmas
,data
) -> Some
(pragmas
,Ast0.rewrap s
(cont data
))
58 let left_mcode (a
,b
,info
,mcodekind
,d
,e
) =
59 match (info
.Ast0.strings_before
,mcodekind
) with
60 ([],_
) | (_
,Ast0.PLUS _
) -> None
61 | (l
,_
) -> Some
(l
,(a
,b
,{info
with Ast0.strings_before
= []},mcodekind
,d
,e
))
63 let right_mcode (a
,b
,info
,mcodekind
,d
,e
) =
64 match (info
.Ast0.strings_after
,mcodekind
) with
65 ([],_
) | (_
,Ast0.PLUS _
) -> None
66 | (l
,_
) -> Some
(l
,(a
,b
,{info
with Ast0.strings_after
= []},mcodekind
,d
,e
))
68 let update_before pragmas
(info
,x
) =
69 ({info
with Ast0.strings_before
= pragmas
@ info
.Ast0.strings_before
},
70 Ast0.PLUS
Ast.ONE
) (* not sure what the arg should be... one seems safe *)
72 let update_after pragmas
(info
,x
) =
73 ({info
with Ast0.strings_after
= info
.Ast0.strings_after
@ pragmas
},
74 Ast0.PLUS
Ast.ONE
) (* not sure what the arg should be... one seems safe *)
76 let rec right_decl d
=
77 match Ast0.unwrap d
with
78 Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
) ->
79 call_right right_mcode sem d
80 (function sem
-> Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
))
81 | Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
) ->
82 call_right right_mcode sem d
83 (function sem
-> Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
))
84 | Ast0.UnInit
(Some stg
,ty
,id
,sem
) ->
85 call_right right_mcode sem d
86 (function sem
-> Ast0.UnInit
(Some stg
,ty
,id
,sem
))
87 | Ast0.UnInit
(None
,ty
,id
,sem
) ->
88 call_right right_mcode sem d
89 (function sem
-> Ast0.UnInit
(None
,ty
,id
,sem
))
90 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) ->
91 call_right right_mcode sem d
92 (function sem
-> Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
))
93 | Ast0.TyDecl
(ty
,sem
) ->
94 call_right right_mcode sem d
95 (function sem
-> Ast0.TyDecl
(ty
,sem
))
96 | Ast0.Typedef
(stg
,ty
,id
,sem
) ->
97 call_right right_mcode sem d
98 (function sem
-> Ast0.Typedef
(stg
,ty
,id
,sem
))
99 | Ast0.DisjDecl
(starter
,decls
,mids
,ender
) -> None
100 | Ast0.Ddots
(dots
,whencode
) -> None
101 | Ast0.OptDecl
(decl
) ->
102 call_right right_decl decl d
(function decl
-> Ast0.OptDecl
(decl
))
103 | Ast0.UniqueDecl
(decl
) ->
104 call_right right_decl decl d
(function decl
-> Ast0.UniqueDecl
(decl
))
106 let rec right_statement s
=
107 match Ast0.unwrap s
with
108 Ast0.FunDecl
(bef
,fi
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) -> None
109 | Ast0.Decl
(bef
,decl
) ->
110 call_right right_decl decl s
111 (function decl
-> Ast0.Decl
(bef
,decl
))
112 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
113 call_right right_mcode rbrace s
114 (function rbrace
-> Ast0.Seq
(lbrace
,body
,rbrace
))
115 | Ast0.ExprStatement
(exp
,sem
) ->
116 call_right right_mcode sem s
117 (function sem
-> Ast0.ExprStatement
(exp
,sem
))
118 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,aft
) -> None
119 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,aft
) -> None
120 | Ast0.While
(whl
,lp
,exp
,rp
,body
,aft
) -> None
121 | Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
) ->
122 call_right right_mcode sem s
123 (function sem
-> Ast0.Do
(d
,body
,whl
,lp
,exp
,rp
,sem
))
124 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,aft
) -> None
125 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,aft
) -> None
126 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
127 call_right right_mcode rb s
128 (function rb
-> Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
))
129 | Ast0.Break
(br
,sem
) ->
130 call_right right_mcode sem s
131 (function sem
-> Ast0.Break
(br
,sem
))
132 | Ast0.Continue
(cont
,sem
) ->
133 call_right right_mcode sem s
134 (function sem
-> Ast0.Continue
(cont
,sem
))
135 | Ast0.Label
(l
,dd
) ->
136 call_right right_mcode dd s
137 (function dd
-> Ast0.Label
(l
,dd
))
138 | Ast0.Goto
(goto
,l
,sem
) ->
139 call_right right_mcode sem s
140 (function sem
-> Ast0.Goto
(goto
,l
,sem
))
141 | Ast0.Return
(ret
,sem
) ->
142 call_right right_mcode sem s
143 (function sem
-> Ast0.Return
(ret
,sem
))
144 | Ast0.ReturnExpr
(ret
,exp
,sem
) ->
145 call_right right_mcode sem s
146 (function sem
-> Ast0.ReturnExpr
(ret
,exp
,sem
))
147 | Ast0.MetaStmt
(name
,pure
) ->
148 call_right right_mcode name s
149 (function name
-> Ast0.MetaStmt
(name
,pure
))
150 | Ast0.MetaStmtList
(name
,pure
) ->
151 call_right right_mcode name s
152 (function name
-> Ast0.MetaStmtList
(name
,pure
))
153 | Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) -> None
154 | Ast0.Nest
(starter
,stmt_dots
,ender
,whn
,multi
) -> None
155 (* the following are None, because they can't be adjacent to an aft node *)
156 | Ast0.Exp
(exp
) -> None
157 | Ast0.TopExp
(exp
) -> None
158 | Ast0.Ty
(ty
) -> None
159 | Ast0.TopInit
(init
) -> None
160 | Ast0.Dots
(d
,whn
) -> None
161 | Ast0.Circles
(d
,whn
) -> None
162 | Ast0.Stars
(d
,whn
) -> None
163 | Ast0.Include
(inc
,name
) ->
164 call_right right_mcode name s
165 (function name
-> Ast0.Include
(inc
,name
))
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.StructUnionName
(kind
,name
) ->
209 call_right left_mcode kind t
210 (function kind
-> Ast0.StructUnionName
(kind
,name
))
211 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) ->
212 call_right left_ty ty t
213 (function ty
-> Ast0.StructUnionDef
(ty
,lb
,decls
,rb
))
214 | Ast0.TypeName
(name
) ->
215 call_right left_mcode name t
(function name
-> Ast0.TypeName
(name
))
216 | Ast0.MetaType
(name
,x
) ->
217 call_right left_mcode name t
(function name
-> Ast0.MetaType
(name
,x
))
218 | Ast0.DisjType
(starter
,types
,mids
,ender
) -> None
219 | Ast0.OptType
(ty
) ->
220 call_right left_ty ty t
(function ty
-> Ast0.OptType
(ty
))
221 | Ast0.UniqueType
(ty
) ->
222 call_right left_ty ty t
(function ty
-> Ast0.UniqueType
(ty
))
224 let rec left_ident i
=
225 match Ast0.unwrap i
with
227 call_right left_mcode name i
228 (function name
-> Ast0.Id
(name
))
229 | Ast0.MetaId
(name
,a
,b
) ->
230 call_right left_mcode name i
231 (function name
-> Ast0.MetaId
(name
,a
,b
))
232 | Ast0.MetaFunc
(name
,a
,b
) ->
233 call_right left_mcode name i
234 (function name
-> Ast0.MetaFunc
(name
,a
,b
))
235 | Ast0.MetaLocalFunc
(name
,a
,b
) ->
236 call_right left_mcode name i
237 (function name
-> Ast0.MetaLocalFunc
(name
,a
,b
))
238 | Ast0.OptIdent
(id
) ->
239 call_right left_ident id i
(function id
-> Ast0.OptIdent
(id
))
240 | Ast0.UniqueIdent
(id
) ->
241 call_right left_ident id i
(function id
-> Ast0.UniqueIdent
(id
))
243 let left_fundecl name fninfo
=
244 let fncall_right processor data cont
=
245 match processor data
with
247 | Some
(pragmas
,data
) -> Some
(pragmas
,cont data
,name
) in
250 (match left_ident name
with
252 | Some
(pragmas
,name
) -> Some
(pragmas
,fninfo
,name
))
253 | (Ast0.FStorage sto
)::x
->
254 fncall_right left_mcode sto
(function sto
-> (Ast0.FStorage sto
)::x
)
255 | (Ast0.FType ty
)::x
->
256 fncall_right left_ty ty
(function ty
-> (Ast0.FType ty
)::x
)
257 | (Ast0.FInline inl
)::x
->
258 fncall_right left_mcode inl
(function inl
-> (Ast0.FInline inl
)::x
)
259 | (Ast0.FAttr atr
)::x
->
260 fncall_right left_mcode atr
(function atr
-> (Ast0.FAttr atr
)::x
)
262 let rec left_decl decl
=
263 match Ast0.unwrap decl
with
264 Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
) ->
265 call_right left_mcode stg decl
266 (function stg
-> Ast0.Init
(Some stg
,ty
,id
,eq
,ini
,sem
))
267 | Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
) ->
268 call_right left_ty ty decl
269 (function ty
-> Ast0.Init
(None
,ty
,id
,eq
,ini
,sem
))
270 | Ast0.UnInit
(Some stg
,ty
,id
,sem
) ->
271 call_right left_mcode stg decl
272 (function stg
-> Ast0.UnInit
(Some stg
,ty
,id
,sem
))
273 | Ast0.UnInit
(None
,ty
,id
,sem
) ->
274 call_right left_ty ty decl
275 (function ty
-> Ast0.UnInit
(None
,ty
,id
,sem
))
276 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) ->
277 call_right left_ident name decl
278 (function name
-> Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
))
279 | Ast0.TyDecl
(ty
,sem
) ->
280 call_right left_ty ty decl
(function ty
-> Ast0.TyDecl
(ty
,sem
))
281 | Ast0.Typedef
(stg
,ty
,id
,sem
) ->
282 call_right left_mcode stg decl
283 (function stg
-> Ast0.Typedef
(stg
,ty
,id
,sem
))
284 | Ast0.DisjDecl
(starter
,decls
,mids
,ender
) -> None
285 | Ast0.Ddots
(dots
,whencode
) -> None
287 call_right left_decl d decl
(function decl
-> Ast0.OptDecl
(decl
))
288 | Ast0.UniqueDecl
(d
) ->
289 call_right left_decl d decl
(function decl
-> Ast0.UniqueDecl
(decl
))
292 let statement r k s
=
295 (match Ast0.unwrap
s with
296 Ast0.FunDecl
(bef
,fi
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
297 (match left_fundecl name fi
with
298 None
-> Ast0.unwrap
s
299 | Some
(pragmas
,fi
,name
) ->
301 (update_after pragmas bef
,
302 fi
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
))
303 | Ast0.Decl
(bef
,decl
) ->
304 (match left_decl decl
with
305 None
-> Ast0.unwrap
s
306 | Some
(pragmas
,decl
) ->
307 Ast0.Decl
(update_after pragmas bef
,decl
))
308 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch1
,aft
) ->
309 (match right_statement branch1
with
310 None
-> Ast0.unwrap
s
311 | Some
(pragmas
,branch1
) ->
313 (iff
,lp
,exp
,rp
,branch1
,update_before pragmas aft
))
314 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,aft
) ->
315 (match right_statement branch2
with
316 None
-> Ast0.unwrap
s
317 | Some
(pragmas
,branch2
) ->
319 (iff
,lp
,exp
,rp
,branch1
,els
,branch2
,
320 update_before pragmas aft
))
321 | Ast0.While
(whl
,lp
,exp
,rp
,body
,aft
) ->
322 (match right_statement body
with
323 None
-> Ast0.unwrap
s
324 | Some
(pragmas
,body
) ->
325 Ast0.While
(whl
,lp
,exp
,rp
,body
,update_before pragmas aft
))
326 | Ast0.For
(fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,aft
) ->
327 (match right_statement body
with
328 None
-> Ast0.unwrap
s
329 | Some
(pragmas
,body
) ->
331 (fr
,lp
,e1
,sem1
,e2
,sem2
,e3
,rp
,body
,
332 update_before pragmas aft
))
333 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,aft
) ->
334 (match right_statement body
with
335 None
-> Ast0.unwrap
s
336 | Some
(pragmas
,body
) ->
337 Ast0.Iterator
(nm
,lp
,args
,rp
,body
,update_before pragmas aft
))
338 | _
-> Ast0.unwrap
s) in
340 let res = V0.rebuilder
341 {V0.rebuilder_functions
with VT0.rebuilder_stmtfn
= statement} in
343 List.map
res.VT0.rebuilder_rec_top_level