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