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