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