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 (* Computes starting and ending logical lines for statements and
26 expressions. every node gets an index as well. *)
28 module Ast0
= Ast0_cocci
29 module Ast
= Ast_cocci
31 (* --------------------------------------------------------------------- *)
34 (* This is a horrible hack. We need to have a special treatment for the code
35 inside a nest, and this is to avoid threading that information around
37 let in_nest_count = ref 0
38 let check_attachable v
= if !in_nest_count > 0 then false else v
40 let mkres x e left right
=
41 let lstart = Ast0.get_info left
in
42 let lend = Ast0.get_info right
in
44 { Ast0.line_start
= lstart.Ast0.pos_info.Ast0.line_start
;
45 Ast0.line_end
= lend.Ast0.pos_info.Ast0.line_end
;
46 Ast0.logical_start
= lstart.Ast0.pos_info.Ast0.logical_start
;
47 Ast0.logical_end
= lend.Ast0.pos_info.Ast0.logical_end
;
48 Ast0.column
= lstart.Ast0.pos_info.Ast0.column
;
49 Ast0.offset
= lstart.Ast0.pos_info.Ast0.offset
;} in
51 { Ast0.pos_info = pos_info;
52 Ast0.attachable_start
= check_attachable lstart.Ast0.attachable_start
;
53 Ast0.attachable_end
= check_attachable lend.Ast0.attachable_end
;
54 Ast0.mcode_start
= lstart.Ast0.mcode_start
;
55 Ast0.mcode_end
= lend.Ast0.mcode_end
;
56 (* only for tokens, not inherited upwards *)
57 Ast0.strings_before
= []; Ast0.strings_after
= [] } in
58 {x
with Ast0.node
= e
; Ast0.info = info}
60 (* This looks like it is there to allow distribution of plus code
61 over disjunctions. But this doesn't work with single_statement, as the
62 plus code has not been distributed to the place that it expects. So the
63 only reasonably easy solution seems to be to disallow distribution. *)
64 (* inherit attachable is because single_statement doesn't work well when +
65 code is attached outside an or, but this has to be allowed after
66 isomorphisms have been introduced. So only set it to true then, or when we
67 know that the code involved cannot contain a statement, ie it is a
69 let inherit_attachable = ref false
70 let mkmultires x e left right
(astart
,start_mcodes
) (aend
,end_mcodes
) =
71 let lstart = Ast0.get_info left
in
72 let lend = Ast0.get_info right
in
74 { Ast0.line_start
= lstart.Ast0.pos_info.Ast0.line_start
;
75 Ast0.line_end
= lend.Ast0.pos_info.Ast0.line_end
;
76 Ast0.logical_start
= lstart.Ast0.pos_info.Ast0.logical_start
;
77 Ast0.logical_end
= lend.Ast0.pos_info.Ast0.logical_end
;
78 Ast0.column
= lstart.Ast0.pos_info.Ast0.column
;
79 Ast0.offset
= lstart.Ast0.pos_info.Ast0.offset
; } in
81 { Ast0.pos_info = pos_info;
82 Ast0.attachable_start
=
83 check_attachable (if !inherit_attachable then astart
else false);
85 check_attachable (if !inherit_attachable then aend
else false);
86 Ast0.mcode_start
= start_mcodes
;
87 Ast0.mcode_end
= end_mcodes
;
88 (* only for tokens, not inherited upwards *)
89 Ast0.strings_before
= []; Ast0.strings_after
= [] } in
90 {x
with Ast0.node
= e
; Ast0.info = info}
92 (* --------------------------------------------------------------------- *)
94 let get_option fn
= function
96 | Some x
-> Some
(fn x
)
98 (* --------------------------------------------------------------------- *)
99 (* --------------------------------------------------------------------- *)
102 let promote_mcode (_
,_
,info,mcodekind
,_
,_
) =
105 Ast0.mcode_start
= [mcodekind
]; Ast0.mcode_end
= [mcodekind
]} in
106 {(Ast0.wrap
()) with Ast0.info = new_info; Ast0.mcodekind
= ref mcodekind
}
108 let promote_mcode_plus_one (_
,_
,info,mcodekind
,_
,_
) =
110 {info.Ast0.pos_info with
111 Ast0.line_start
= info.Ast0.pos_info.Ast0.line_start
+ 1;
112 Ast0.logical_start
= info.Ast0.pos_info.Ast0.logical_start
+ 1;
113 Ast0.line_end
= info.Ast0.pos_info.Ast0.line_end
+ 1;
114 Ast0.logical_end
= info.Ast0.pos_info.Ast0.logical_end
+ 1; } in
117 Ast0.pos_info = new_pos_info;
118 Ast0.mcode_start
= [mcodekind
]; Ast0.mcode_end
= [mcodekind
]} in
119 {(Ast0.wrap
()) with Ast0.info = new_info; Ast0.mcodekind
= ref mcodekind
}
121 let promote_to_statement stm mcodekind
=
122 let info = Ast0.get_info stm
in
124 {info.Ast0.pos_info with
125 Ast0.logical_start
= info.Ast0.pos_info.Ast0.logical_end
;
126 Ast0.line_start
= info.Ast0.pos_info.Ast0.line_end
; } in
129 Ast0.pos_info = new_pos_info;
130 Ast0.mcode_start
= [mcodekind
]; Ast0.mcode_end
= [mcodekind
];
131 Ast0.attachable_start
= check_attachable true;
132 Ast0.attachable_end
= check_attachable true} in
133 {(Ast0.wrap
()) with Ast0.info = new_info; Ast0.mcodekind
= ref mcodekind
}
135 let promote_to_statement_start stm mcodekind
=
136 let info = Ast0.get_info stm
in
138 {info.Ast0.pos_info with
139 Ast0.logical_end
= info.Ast0.pos_info.Ast0.logical_start
;
140 Ast0.line_end
= info.Ast0.pos_info.Ast0.line_start
; } in
143 Ast0.pos_info = new_pos_info;
144 Ast0.mcode_start
= [mcodekind
]; Ast0.mcode_end
= [mcodekind
];
145 Ast0.attachable_start
= check_attachable true;
146 Ast0.attachable_end
= check_attachable true} in
147 {(Ast0.wrap
()) with Ast0.info = new_info; Ast0.mcodekind
= ref mcodekind
}
149 (* mcode is good by default *)
150 let bad_mcode (t
,a
,info,mcodekind
,pos
,adj
) =
153 Ast0.attachable_start
= check_attachable false;
154 Ast0.attachable_end
= check_attachable false} in
155 (t
,a
,new_info,mcodekind
,pos
,adj
)
157 let get_all_start_info l
=
158 (List.for_all
(function x
-> (Ast0.get_info x
).Ast0.attachable_start
) l
,
159 List.concat
(List.map
(function x
-> (Ast0.get_info x
).Ast0.mcode_start
) l
))
161 let get_all_end_info l
=
162 (List.for_all
(function x
-> (Ast0.get_info x
).Ast0.attachable_end
) l
,
163 List.concat
(List.map
(function x
-> (Ast0.get_info x
).Ast0.mcode_end
) l
))
165 (* --------------------------------------------------------------------- *)
168 (* for the logline classification and the mcode field, on both sides, skip
169 over initial minus dots, as they don't contribute anything *)
170 let dot_list is_dots fn
= function
171 [] -> failwith
"dots should not be empty"
174 let first = List.hd l
in
176 match (is_dots
first, l
) with (true,_
::x
::_
) -> x
| _
-> first in
177 (* get the logline decorator and the mcodekind of the chosen node *)
178 fn
(Ast0.get_info
chosen) in
179 let forward = List.map fn l
in
180 let backward = List.rev
forward in
181 let (first_attachable
,first_mcode
) =
183 (function x
-> (x
.Ast0.attachable_start
,x
.Ast0.mcode_start
)) in
184 let (last_attachable
,last_mcode
) =
186 (function x
-> (x
.Ast0.attachable_end
,x
.Ast0.mcode_end
)) in
187 let first = List.hd
forward in
188 let last = List.hd
backward in
190 { (Ast0.get_info
first) with
191 Ast0.attachable_start
= check_attachable first_attachable
;
192 Ast0.mcode_start
= first_mcode
} in
194 { (Ast0.get_info
last) with
195 Ast0.attachable_end
= check_attachable last_attachable
;
196 Ast0.mcode_end
= last_mcode
} in
197 let first = Ast0.set_info
first first_info in
198 let last = Ast0.set_info
last last_info in
201 let dots is_dots prev fn d
=
202 match (prev
,Ast0.unwrap d
) with
203 (Some prev
,Ast0.DOTS
([])) ->
204 mkres d
(Ast0.DOTS
[]) prev prev
205 | (None
,Ast0.DOTS
([])) ->
209 Ast0.attachable_start
= check_attachable false;
210 Ast0.attachable_end
= check_attachable false}
211 | (_
,Ast0.DOTS
(x
)) ->
212 let (l
,lstart,lend) = dot_list is_dots fn x
in
213 mkres d
(Ast0.DOTS l
) lstart lend
214 | (_
,Ast0.CIRCLES
(x
)) ->
215 let (l
,lstart,lend) = dot_list is_dots fn x
in
216 mkres d
(Ast0.CIRCLES l
) lstart lend
217 | (_
,Ast0.STARS
(x
)) ->
218 let (l
,lstart,lend) = dot_list is_dots fn x
in
219 mkres d
(Ast0.STARS l
) lstart lend
221 (* --------------------------------------------------------------------- *)
224 (* for #define name, with no value, to compute right side *)
225 let mkidres a b c d r
= (mkres a b c d
,r
)
227 let rec full_ident i
=
228 match Ast0.unwrap i
with
229 Ast0.Id
(name
) as ui
->
230 let name = promote_mcode name in mkidres i ui
name name name
231 | Ast0.MetaId
(name,_
,_
)
232 | Ast0.MetaFunc
(name,_
,_
) | Ast0.MetaLocalFunc
(name,_
,_
) as ui
->
233 let name = promote_mcode name in mkidres i ui
name name name
234 | Ast0.OptIdent
(id
) ->
235 let (id
,r
) = full_ident id
in mkidres i
(Ast0.OptIdent
(id
)) id id r
236 | Ast0.UniqueIdent
(id
) ->
237 let (id
,r
) = full_ident id
in mkidres i
(Ast0.UniqueIdent
(id
)) id id r
238 and ident i
= let (id
,_
) = full_ident i
in id
240 (* --------------------------------------------------------------------- *)
244 match Ast0.unwrap e
with
245 Ast0.Edots
(_
,_
) | Ast0.Ecircles
(_
,_
) | Ast0.Estars
(_
,_
) -> true
248 let rec expression e
=
249 match Ast0.unwrap e
with
252 mkres e
(Ast0.Ident
(id)) id id
253 | Ast0.Constant
(const
) as ue
->
254 let ln = promote_mcode const
in
256 | Ast0.FunCall
(fn
,lp
,args
,rp
) ->
257 let fn = expression fn in
258 let args = dots is_exp_dots (Some
(promote_mcode lp
)) expression args in
259 mkres e
(Ast0.FunCall
(fn,lp
,args,rp
)) fn (promote_mcode rp
)
260 | Ast0.Assignment
(left
,op
,right
,simple
) ->
261 let left = expression left in
262 let right = expression right in
263 mkres e
(Ast0.Assignment
(left,op
,right,simple
)) left right
264 | Ast0.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) ->
265 let exp1 = expression exp1 in
266 let exp2 = get_option expression exp2 in
267 let exp3 = expression exp3 in
268 mkres e
(Ast0.CondExpr
(exp1,why
,exp2,colon
,exp3)) exp1 exp3
269 | Ast0.Postfix
(exp
,op
) ->
270 let exp = expression exp in
271 mkres e
(Ast0.Postfix
(exp,op
)) exp (promote_mcode op
)
272 | Ast0.Infix
(exp,op
) ->
273 let exp = expression exp in
274 mkres e
(Ast0.Infix
(exp,op
)) (promote_mcode op
) exp
275 | Ast0.Unary
(exp,op
) ->
276 let exp = expression exp in
277 mkres e
(Ast0.Unary
(exp,op
)) (promote_mcode op
) exp
278 | Ast0.Binary
(left,op
,right) ->
279 let left = expression left in
280 let right = expression right in
281 mkres e
(Ast0.Binary
(left,op
,right)) left right
282 | Ast0.Nested
(left,op
,right) ->
283 let left = expression left in
284 let right = expression right in
285 mkres e
(Ast0.Nested
(left,op
,right)) left right
286 | Ast0.Paren
(lp
,exp,rp
) ->
287 mkres e
(Ast0.Paren
(lp
,expression exp,rp
))
288 (promote_mcode lp
) (promote_mcode rp
)
289 | Ast0.ArrayAccess
(exp1,lb
,exp2,rb
) ->
290 let exp1 = expression exp1 in
291 let exp2 = expression exp2 in
292 mkres e
(Ast0.ArrayAccess
(exp1,lb
,exp2,rb
)) exp1 (promote_mcode rb
)
293 | Ast0.RecordAccess
(exp,pt
,field
) ->
294 let exp = expression exp in
295 let field = ident
field in
296 mkres e
(Ast0.RecordAccess
(exp,pt
,field)) exp field
297 | Ast0.RecordPtAccess
(exp,ar
,field) ->
298 let exp = expression exp in
299 let field = ident
field in
300 mkres e
(Ast0.RecordPtAccess
(exp,ar
,field)) exp field
301 | Ast0.Cast
(lp
,ty
,rp
,exp) ->
302 let exp = expression exp in
303 mkres e
(Ast0.Cast
(lp
,typeC ty
,rp
,exp)) (promote_mcode lp
) exp
304 | Ast0.SizeOfExpr
(szf
,exp) ->
305 let exp = expression exp in
306 mkres e
(Ast0.SizeOfExpr
(szf
,exp)) (promote_mcode szf
) exp
307 | Ast0.SizeOfType
(szf
,lp
,ty
,rp
) ->
308 mkres e
(Ast0.SizeOfType
(szf
,lp
,typeC ty
,rp
))
309 (promote_mcode szf
) (promote_mcode rp
)
310 | Ast0.TypeExp
(ty
) ->
311 let ty = typeC
ty in mkres e
(Ast0.TypeExp
(ty)) ty ty
312 | Ast0.MetaErr
(name,_
,_
) | Ast0.MetaExpr
(name,_
,_
,_
,_
)
313 | Ast0.MetaExprList
(name,_
,_
) as ue
->
314 let ln = promote_mcode name in mkres e ue
ln ln
316 (*let cm = bad_mcode cm in*) (* why was this bad??? *)
317 let ln = promote_mcode cm in
318 mkres e
(Ast0.EComma
(cm)) ln ln
319 | Ast0.DisjExpr
(starter
,exps
,mids
,ender
) ->
320 let starter = bad_mcode starter in
321 let exps = List.map
expression exps in
322 let mids = List.map
bad_mcode mids in
323 let ender = bad_mcode ender in
324 mkmultires e
(Ast0.DisjExpr
(starter,exps,mids,ender))
325 (promote_mcode starter) (promote_mcode ender)
326 (get_all_start_info exps) (get_all_end_info exps)
327 | Ast0.NestExpr
(starter,exp_dots
,ender,whencode
,multi
) ->
328 let exp_dots = dots is_exp_dots None
expression exp_dots in
329 let starter = bad_mcode starter in
330 let ender = bad_mcode ender in
331 mkres e
(Ast0.NestExpr
(starter,exp_dots,ender,whencode
,multi
))
332 (promote_mcode starter) (promote_mcode ender)
333 | Ast0.Edots
(dots,whencode
) ->
334 let dots = bad_mcode dots in
335 let ln = promote_mcode dots in
336 mkres e
(Ast0.Edots
(dots,whencode
)) ln ln
337 | Ast0.Ecircles
(dots,whencode
) ->
338 let dots = bad_mcode dots in
339 let ln = promote_mcode dots in
340 mkres e
(Ast0.Ecircles
(dots,whencode
)) ln ln
341 | Ast0.Estars
(dots,whencode
) ->
342 let dots = bad_mcode dots in
343 let ln = promote_mcode dots in
344 mkres e
(Ast0.Estars
(dots,whencode
)) ln ln
345 | Ast0.OptExp
(exp) ->
346 let exp = expression exp in
347 mkres e
(Ast0.OptExp
(exp)) exp exp
348 | Ast0.UniqueExp
(exp) ->
349 let exp = expression exp in
350 mkres e
(Ast0.UniqueExp
(exp)) exp exp
352 and expression_dots x
= dots is_exp_dots None
expression x
354 (* --------------------------------------------------------------------- *)
358 match Ast0.unwrap t
with
359 Ast0.ConstVol
(cv
,ty) ->
361 mkres t
(Ast0.ConstVol
(cv
,ty)) (promote_mcode cv
) ty
362 | Ast0.BaseType
(ty,strings
) as ut
->
363 let first = List.hd strings
in
364 let last = List.hd
(List.rev strings
) in
365 mkres t ut
(promote_mcode first) (promote_mcode last)
366 | Ast0.Signed
(sgn
,None
) as ut
->
367 mkres t ut
(promote_mcode sgn
) (promote_mcode sgn
)
368 | Ast0.Signed
(sgn
,Some
ty) ->
370 mkres t
(Ast0.Signed
(sgn
,Some
ty)) (promote_mcode sgn
) ty
371 | Ast0.Pointer
(ty,star
) ->
373 mkres t
(Ast0.Pointer
(ty,star
)) ty (promote_mcode star
)
374 | Ast0.FunctionPointer
(ty,lp1
,star
,rp1
,lp2
,params
,rp2
) ->
376 let params = parameter_list
(Some
(promote_mcode lp2
)) params in
377 mkres t
(Ast0.FunctionPointer
(ty,lp1
,star
,rp1
,lp2
,params,rp2
))
378 ty (promote_mcode rp2
)
379 | Ast0.FunctionType
(Some
ty,lp1
,params,rp1
) ->
381 let params = parameter_list
(Some
(promote_mcode lp1
)) params in
382 let res = Ast0.FunctionType
(Some
ty,lp1
,params,rp1
) in
383 mkres t
res ty (promote_mcode rp1
)
384 | Ast0.FunctionType
(None
,lp1
,params,rp1
) ->
385 let params = parameter_list
(Some
(promote_mcode lp1
)) params in
386 let res = Ast0.FunctionType
(None
,lp1
,params,rp1
) in
387 mkres t
res (promote_mcode lp1
) (promote_mcode rp1
)
388 | Ast0.Array
(ty,lb
,size
,rb
) ->
390 mkres t
(Ast0.Array
(ty,lb
,get_option expression size
,rb
))
391 ty (promote_mcode rb
)
392 | Ast0.EnumName
(kind
,name) ->
393 let name = ident
name in
394 mkres t
(Ast0.EnumName
(kind
,name)) (promote_mcode kind
) name
395 | Ast0.StructUnionName
(kind
,Some
name) ->
396 let name = ident
name in
397 mkres t
(Ast0.StructUnionName
(kind
,Some
name)) (promote_mcode kind
) name
398 | Ast0.StructUnionName
(kind
,None
) ->
399 let mc = promote_mcode kind
in
400 mkres t
(Ast0.StructUnionName
(kind
,None
)) mc mc
401 | Ast0.StructUnionDef
(ty,lb
,decls
,rb
) ->
404 dots is_decl_dots
(Some
(promote_mcode lb
)) declaration
decls in
405 mkres t
(Ast0.StructUnionDef
(ty,lb
,decls,rb
)) ty (promote_mcode rb
)
406 | Ast0.TypeName
(name) as ut
->
407 let ln = promote_mcode name in mkres t ut
ln ln
408 | Ast0.MetaType
(name,_
) as ut
->
409 let ln = promote_mcode name in mkres t ut
ln ln
410 | Ast0.DisjType
(starter,types
,mids,ender) ->
411 let starter = bad_mcode starter in
412 let types = List.map typeC
types in
413 let mids = List.map
bad_mcode mids in
414 let ender = bad_mcode ender in
415 mkmultires t
(Ast0.DisjType
(starter,types,mids,ender))
416 (promote_mcode starter) (promote_mcode ender)
417 (get_all_start_info types) (get_all_end_info types)
418 | Ast0.OptType
(ty) ->
419 let ty = typeC
ty in mkres t
(Ast0.OptType
(ty)) ty ty
420 | Ast0.UniqueType
(ty) ->
421 let ty = typeC
ty in mkres t
(Ast0.UniqueType
(ty)) ty ty
423 (* --------------------------------------------------------------------- *)
424 (* Variable declaration *)
425 (* Even if the Cocci program specifies a list of declarations, they are
426 split out into multiple declarations of a single variable each. *)
429 match Ast0.unwrap s
with
430 Ast0.Ddots
(_
,_
) -> true
434 match Ast0.unwrap d
with
435 (Ast0.MetaDecl
(name,_
) | Ast0.MetaField
(name,_
)) as up
->
436 let ln = promote_mcode name in mkres d up
ln ln
437 | Ast0.Init
(stg
,ty,id,eq
,exp,sem
) ->
440 let exp = initialiser
exp in
443 mkres d
(Ast0.Init
(stg
,ty,id,eq
,exp,sem
)) ty (promote_mcode sem
)
445 mkres d
(Ast0.Init
(stg
,ty,id,eq
,exp,sem
))
446 (promote_mcode x
) (promote_mcode sem
))
447 | Ast0.UnInit
(stg
,ty,id,sem
) ->
452 mkres d
(Ast0.UnInit
(stg
,ty,id,sem
)) ty (promote_mcode sem
)
454 mkres d
(Ast0.UnInit
(stg
,ty,id,sem
))
455 (promote_mcode x
) (promote_mcode sem
))
456 | Ast0.MacroDecl
(name,lp
,args,rp
,sem
) ->
457 let name = ident
name in
458 let args = dots is_exp_dots (Some
(promote_mcode lp
)) expression args in
459 mkres d
(Ast0.MacroDecl
(name,lp
,args,rp
,sem
)) name (promote_mcode sem
)
460 | Ast0.TyDecl
(ty,sem
) ->
462 mkres d
(Ast0.TyDecl
(ty,sem
)) ty (promote_mcode sem
)
463 | Ast0.Typedef
(stg
,ty,id,sem
) ->
466 mkres d
(Ast0.Typedef
(stg
,ty,id,sem
))
467 (promote_mcode stg
) (promote_mcode sem
)
468 | Ast0.DisjDecl
(starter,decls,mids,ender) ->
469 let starter = bad_mcode starter in
470 let decls = List.map declaration
decls in
471 let mids = List.map
bad_mcode mids in
472 let ender = bad_mcode ender in
473 mkmultires d
(Ast0.DisjDecl
(starter,decls,mids,ender))
474 (promote_mcode starter) (promote_mcode ender)
475 (get_all_start_info decls) (get_all_end_info decls)
476 | Ast0.Ddots
(dots,whencode
) ->
477 let dots = bad_mcode dots in
478 let ln = promote_mcode dots in
479 mkres d
(Ast0.Ddots
(dots,whencode
)) ln ln
480 | Ast0.OptDecl
(decl
) ->
481 let decl = declaration
decl in
482 mkres d
(Ast0.OptDecl
(declaration
decl)) decl decl
483 | Ast0.UniqueDecl
(decl) ->
484 let decl = declaration
decl in
485 mkres d
(Ast0.UniqueDecl
(declaration
decl)) decl decl
487 (* --------------------------------------------------------------------- *)
491 match Ast0.unwrap i
with
492 Ast0.Idots
(_
,_
) -> true
496 match Ast0.unwrap i
with
497 Ast0.MetaInit
(name,_
) as ut
->
498 let ln = promote_mcode name in mkres i ut
ln ln
499 | Ast0.InitExpr
(exp) ->
500 let exp = expression exp in
501 mkres i
(Ast0.InitExpr
(exp)) exp exp
502 | Ast0.InitList
(lb
,initlist
,rb
) ->
504 dots is_init_dots
(Some
(promote_mcode lb
)) initialiser
initlist in
505 mkres i
(Ast0.InitList
(lb
,initlist,rb
))
506 (promote_mcode lb
) (promote_mcode rb
)
507 | Ast0.InitGccExt
(designators
,eq
,ini
) ->
508 let (delims
,designators
) = (* non empty due to parsing *)
509 List.split
(List.map designator designators
) in
510 let ini = initialiser
ini in
511 mkres i
(Ast0.InitGccExt
(designators
,eq
,ini))
512 (promote_mcode (List.hd delims
)) ini
513 | Ast0.InitGccName
(name,eq
,ini) ->
514 let name = ident
name in
515 let ini = initialiser
ini in
516 mkres i
(Ast0.InitGccName
(name,eq
,ini)) name ini
517 | Ast0.IComma
(cm) as up
->
518 let ln = promote_mcode cm in mkres i up
ln ln
519 | Ast0.Idots
(dots,whencode
) ->
520 let dots = bad_mcode dots in
521 let ln = promote_mcode dots in
522 mkres i
(Ast0.Idots
(dots,whencode
)) ln ln
523 | Ast0.OptIni
(ini) ->
524 let ini = initialiser
ini in
525 mkres i
(Ast0.OptIni
(ini)) ini ini
526 | Ast0.UniqueIni
(ini) ->
527 let ini = initialiser
ini in
528 mkres i
(Ast0.UniqueIni
(ini)) ini ini
530 and designator
= function
531 Ast0.DesignatorField
(dot
,id) ->
532 (dot
,Ast0.DesignatorField
(dot
,ident
id))
533 | Ast0.DesignatorIndex
(lb
,exp,rb
) ->
534 (lb
,Ast0.DesignatorIndex
(lb
,expression exp,rb
))
535 | Ast0.DesignatorRange
(lb
,min
,dots,max
,rb
) ->
536 (lb
,Ast0.DesignatorRange
(lb
,expression min
,dots,expression max
,rb
))
538 and initialiser_list prev
= dots is_init_dots prev initialiser
541 and initialiser_dots x
= dots is_init_dots None initialiser x
543 (* --------------------------------------------------------------------- *)
546 and is_param_dots p
=
547 match Ast0.unwrap p
with
548 Ast0.Pdots
(_
) | Ast0.Pcircles
(_
) -> true
551 and parameterTypeDef p
=
552 match Ast0.unwrap p
with
553 Ast0.VoidParam
(ty) ->
554 let ty = typeC
ty in mkres p
(Ast0.VoidParam
(ty)) ty ty
555 | Ast0.Param
(ty,Some
id) ->
557 let ty = typeC
ty in mkres p
(Ast0.Param
(ty,Some
id)) ty id
558 | Ast0.Param
(ty,None
) ->
559 let ty = typeC
ty in mkres p
(Ast0.Param
(ty,None
)) ty ty
560 | Ast0.MetaParam
(name,_
) as up
->
561 let ln = promote_mcode name in mkres p up
ln ln
562 | Ast0.MetaParamList
(name,_
,_
) as up
->
563 let ln = promote_mcode name in mkres p up
ln ln
565 (*let cm = bad_mcode cm in*) (* why was this bad??? *)
566 let ln = promote_mcode cm in
567 mkres p
(Ast0.PComma
(cm)) ln ln
568 | Ast0.Pdots
(dots) ->
569 let dots = bad_mcode dots in
570 let ln = promote_mcode dots in
571 mkres p
(Ast0.Pdots
(dots)) ln ln
572 | Ast0.Pcircles
(dots) ->
573 let dots = bad_mcode dots in
574 let ln = promote_mcode dots in
575 mkres p
(Ast0.Pcircles
(dots)) ln ln
576 | Ast0.OptParam
(param
) ->
577 let res = parameterTypeDef param
in
578 mkres p
(Ast0.OptParam
(res)) res res
579 | Ast0.UniqueParam
(param
) ->
580 let res = parameterTypeDef param
in
581 mkres p
(Ast0.UniqueParam
(res)) res res
583 and parameter_list prev
= dots is_param_dots prev parameterTypeDef
586 let parameter_dots x
= dots is_param_dots None parameterTypeDef x
588 (* --------------------------------------------------------------------- *)
590 let is_define_param_dots s
=
591 match Ast0.unwrap s
with
592 Ast0.DPdots
(_
) | Ast0.DPcircles
(_
) -> true
595 let rec define_param p
=
596 match Ast0.unwrap p
with
598 let id = ident
id in mkres p
(Ast0.DParam
(id)) id id
599 | Ast0.DPComma
(cm) ->
600 (*let cm = bad_mcode cm in*) (* why was this bad??? *)
601 let ln = promote_mcode cm in
602 mkres p
(Ast0.DPComma
(cm)) ln ln
603 | Ast0.DPdots
(dots) ->
604 let dots = bad_mcode dots in
605 let ln = promote_mcode dots in
606 mkres p
(Ast0.DPdots
(dots)) ln ln
607 | Ast0.DPcircles
(dots) ->
608 let dots = bad_mcode dots in
609 let ln = promote_mcode dots in
610 mkres p
(Ast0.DPcircles
(dots)) ln ln
611 | Ast0.OptDParam
(dp
) ->
612 let res = define_param dp
in
613 mkres p
(Ast0.OptDParam
(res)) res res
614 | Ast0.UniqueDParam
(dp
) ->
615 let res = define_param dp
in
616 mkres p
(Ast0.UniqueDParam
(res)) res res
618 let define_parameters x
id =
619 match Ast0.unwrap x
with
620 Ast0.NoParams
-> (x
,id) (* no info, should be ignored *)
621 | Ast0.DParams
(lp
,dp
,rp
) ->
622 let dp = dots is_define_param_dots None
define_param dp in
623 let l = promote_mcode lp
in
624 let r = promote_mcode rp
in
625 (mkres x
(Ast0.DParams
(lp
,dp,rp
)) l r, r)
627 (* --------------------------------------------------------------------- *)
631 match Ast0.unwrap s
with
632 Ast0.Dots
(_
,_
) | Ast0.Circles
(_
,_
) | Ast0.Stars
(_
,_
) -> true
635 let rec statement s
=
637 match Ast0.unwrap s
with
638 Ast0.Decl
((_
,bef
),decl) ->
639 let decl = declaration
decl in
640 let left = promote_to_statement_start decl bef
in
641 mkres s
(Ast0.Decl
((Ast0.get_info
left,bef
),decl)) decl decl
642 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
644 dots is_stm_dots (Some
(promote_mcode lbrace
)) statement body in
645 mkres s
(Ast0.Seq
(lbrace
,body,rbrace
))
646 (promote_mcode lbrace
) (promote_mcode rbrace
)
647 | Ast0.ExprStatement
(exp,sem
) ->
648 let exp = expression exp in
649 mkres s
(Ast0.ExprStatement
(exp,sem
)) exp (promote_mcode sem
)
650 | Ast0.IfThen
(iff
,lp
,exp,rp
,branch
,(_
,aft
)) ->
651 let exp = expression exp in
652 let branch = statement branch in
653 let right = promote_to_statement branch aft
in
654 mkres s
(Ast0.IfThen
(iff
,lp
,exp,rp
,branch,(Ast0.get_info
right,aft
)))
655 (promote_mcode iff
) right
656 | Ast0.IfThenElse
(iff
,lp
,exp,rp
,branch1
,els
,branch2
,(_
,aft
)) ->
657 let exp = expression exp in
658 let branch1 = statement branch1 in
659 let branch2 = statement branch2 in
660 let right = promote_to_statement branch2 aft
in
662 (Ast0.IfThenElse
(iff
,lp
,exp,rp
,branch1,els
,branch2,
663 (Ast0.get_info
right,aft
)))
664 (promote_mcode iff
) right
665 | Ast0.While
(wh
,lp
,exp,rp
,body,(_
,aft
)) ->
666 let exp = expression exp in
667 let body = statement body in
668 let right = promote_to_statement body aft
in
669 mkres s
(Ast0.While
(wh
,lp
,exp,rp
,body,(Ast0.get_info
right,aft
)))
670 (promote_mcode wh
) right
671 | Ast0.Do
(d
,body,wh
,lp
,exp,rp
,sem
) ->
672 let body = statement body in
673 let exp = expression exp in
674 mkres s
(Ast0.Do
(d
,body,wh
,lp
,exp,rp
,sem
))
675 (promote_mcode d
) (promote_mcode sem
)
676 | Ast0.For
(fr
,lp
,exp1,sem1
,exp2,sem2
,exp3,rp
,body,(_
,aft
)) ->
677 let exp1 = get_option expression exp1 in
678 let exp2 = get_option expression exp2 in
679 let exp3 = get_option expression exp3 in
680 let body = statement body in
681 let right = promote_to_statement body aft
in
682 mkres s
(Ast0.For
(fr
,lp
,exp1,sem1
,exp2,sem2
,exp3,rp
,body,
683 (Ast0.get_info
right,aft
)))
684 (promote_mcode fr
) right
685 | Ast0.Iterator
(nm
,lp
,args,rp
,body,(_
,aft
)) ->
687 let args = dots is_exp_dots (Some
(promote_mcode lp
)) expression args in
688 let body = statement body in
689 let right = promote_to_statement body aft
in
690 mkres s
(Ast0.Iterator
(nm,lp
,args,rp
,body,(Ast0.get_info
right,aft
)))
692 | Ast0.Switch
(switch
,lp
,exp,rp
,lb
,decls,cases
,rb
) ->
693 let exp = expression exp in
695 dots is_stm_dots (Some
(promote_mcode lb
))
698 dots (function _
-> false)
699 (if Ast0.undots
decls = []
700 then (Some
(promote_mcode lb
))
701 else None
(* not sure this is right, but not sure the case can
705 (Ast0.Switch
(switch
,lp
,exp,rp
,lb
,decls,cases,rb
))
706 (promote_mcode switch
) (promote_mcode rb
)
707 | Ast0.Break
(br
,sem
) as us
->
708 mkres s us
(promote_mcode br
) (promote_mcode sem
)
709 | Ast0.Continue
(cont
,sem
) as us
->
710 mkres s us
(promote_mcode cont
) (promote_mcode sem
)
711 | Ast0.Label
(l,dd
) ->
713 mkres s
(Ast0.Label
(l,dd
)) l (promote_mcode dd
)
714 | Ast0.Goto
(goto
,id,sem
) ->
716 mkres s
(Ast0.Goto
(goto
,id,sem
))
717 (promote_mcode goto
) (promote_mcode sem
)
718 | Ast0.Return
(ret
,sem
) as us
->
719 mkres s us
(promote_mcode ret
) (promote_mcode sem
)
720 | Ast0.ReturnExpr
(ret
,exp,sem
) ->
721 let exp = expression exp in
722 mkres s
(Ast0.ReturnExpr
(ret
,exp,sem
))
723 (promote_mcode ret
) (promote_mcode sem
)
724 | Ast0.MetaStmt
(name,_
)
725 | Ast0.MetaStmtList
(name,_
) as us
->
726 let ln = promote_mcode name in mkres s us
ln ln
728 let exp = expression exp in
729 mkres s
(Ast0.Exp
(exp)) exp exp
730 | Ast0.TopExp
(exp) ->
731 let exp = expression exp in
732 mkres s
(Ast0.TopExp
(exp)) exp exp
735 mkres s
(Ast0.Ty
(ty)) ty ty
736 | Ast0.TopInit
(init
) ->
737 let init = initialiser
init in
738 mkres s
(Ast0.TopInit
(init)) init init
739 | Ast0.Disj
(starter,rule_elem_dots_list
,mids,ender) ->
740 let starter = bad_mcode starter in
741 let mids = List.map
bad_mcode mids in
742 let ender = bad_mcode ender in
743 let rec loop prevs
= function
746 (dots is_stm_dots (Some
(promote_mcode_plus_one(List.hd prevs
)))
748 (loop (List.tl prevs
) stms
) in
749 let elems = loop (starter::mids) rule_elem_dots_list
in
750 mkmultires s
(Ast0.Disj
(starter,elems,mids,ender))
751 (promote_mcode starter) (promote_mcode ender)
752 (get_all_start_info elems) (get_all_end_info elems)
753 | Ast0.Nest
(starter,rule_elem_dots
,ender,whencode
,multi
) ->
754 let starter = bad_mcode starter in
755 let ender = bad_mcode ender in
757 match Ast0.get_mcode_mcodekind
starter with
759 (* if minus, then all nest code has to be minus. This is
760 checked at the token level, in parse_cocci.ml. All nest code
761 is also unattachable. We strip the minus annotations from
762 the nest code because in the CTL another metavariable will
763 take care of removing all the code matched by the nest.
764 Without stripping the minus annotations, we would get a
765 double transformation. Perhaps there is a more elegant
766 way to do this in the CTL, but it is not easy, because of
767 the interaction with the whencode and the implementation of
769 in_nest_count := !in_nest_count + 1;
771 in_nest_count := !in_nest_count - 1;
776 (function _
-> dots is_stm_dots None
statement rule_elem_dots) in
777 mkres s
(Ast0.Nest
(starter,rule_elem_dots,ender,whencode
,multi
))
778 (promote_mcode starter) (promote_mcode ender)
779 | Ast0.Dots
(dots,whencode
) ->
780 let dots = bad_mcode dots in
781 let ln = promote_mcode dots in
782 mkres s
(Ast0.Dots
(dots,whencode
)) ln ln
783 | Ast0.Circles
(dots,whencode
) ->
784 let dots = bad_mcode dots in
785 let ln = promote_mcode dots in
786 mkres s
(Ast0.Circles
(dots,whencode
)) ln ln
787 | Ast0.Stars
(dots,whencode
) ->
788 let dots = bad_mcode dots in
789 let ln = promote_mcode dots in
790 mkres s
(Ast0.Stars
(dots,whencode
)) ln ln
791 | Ast0.FunDecl
((_
,bef
),fninfo
,name,lp
,params,rp
,lbrace
,body,rbrace
) ->
794 (function Ast0.FType
(ty) -> Ast0.FType
(typeC
ty) | x
-> x
)
796 let name = ident
name in
797 let params = parameter_list
(Some
(promote_mcode lp
)) params in
799 dots is_stm_dots (Some
(promote_mcode lbrace
)) statement body in
801 (* cases on what is leftmost *)
803 [] -> promote_to_statement_start name bef
804 | Ast0.FStorage
(stg
)::_
->
805 promote_to_statement_start (promote_mcode stg
) bef
806 | Ast0.FType
(ty)::_
->
807 promote_to_statement_start ty bef
808 | Ast0.FInline
(inline
)::_
->
809 promote_to_statement_start (promote_mcode inline
) bef
810 | Ast0.FAttr
(attr
)::_
->
811 promote_to_statement_start (promote_mcode attr
) bef
in
812 (* pretend it is one line before the start of the function, so that it
813 will catch things defined at top level. We assume that these will not
814 be defined on the same line as the function. This is a HACK.
815 A better approach would be to attach top_level things to this node,
816 and other things to the node after, but that would complicate
817 insert_plus, which doesn't distinguish between different mcodekinds *)
819 Ast0.FunDecl
((Ast0.get_info
left,bef
),fninfo,name,lp
,params,rp
,lbrace
,
821 (* have to do this test again, because of typing problems - can't save
822 the result, only use it *)
824 [] -> mkres s
res name (promote_mcode rbrace
)
825 | Ast0.FStorage
(stg
)::_
->
826 mkres s
res (promote_mcode stg
) (promote_mcode rbrace
)
827 | Ast0.FType
(ty)::_
-> mkres s
res ty (promote_mcode rbrace
)
828 | Ast0.FInline
(inline
)::_
->
829 mkres s
res (promote_mcode inline
) (promote_mcode rbrace
)
830 | Ast0.FAttr
(attr
)::_
->
831 mkres s
res (promote_mcode attr
) (promote_mcode rbrace
))
833 | Ast0.Include
(inc
,stm
) ->
834 mkres s
(Ast0.Include
(inc
,stm
)) (promote_mcode inc
) (promote_mcode stm
)
835 | Ast0.Define
(def
,id,params,body) ->
836 let (id,right) = full_ident id in
837 let (params,prev
) = define_parameters params right in
838 let body = dots is_stm_dots (Some prev
) statement body in
839 mkres s
(Ast0.Define
(def
,id,params,body)) (promote_mcode def
) body
840 | Ast0.OptStm
(stm
) ->
841 let stm = statement stm in mkres s
(Ast0.OptStm
(stm)) stm stm
842 | Ast0.UniqueStm
(stm) ->
843 let stm = statement stm in mkres s
(Ast0.UniqueStm
(stm)) stm stm in
844 Ast0.set_dots_bef_aft
res
845 (match Ast0.get_dots_bef_aft
res with
846 Ast0.NoDots
-> Ast0.NoDots
847 | Ast0.AddingBetweenDots s
->
848 Ast0.AddingBetweenDots
(statement s
)
849 | Ast0.DroppingBetweenDots s
->
850 Ast0.DroppingBetweenDots
(statement s
))
853 match Ast0.unwrap c
with
854 Ast0.Default
(def
,colon
,code
) ->
855 let code = dots is_stm_dots (Some
(promote_mcode colon
)) statement code in
856 mkres c
(Ast0.Default
(def
,colon
,code)) (promote_mcode def
) code
857 | Ast0.Case
(case
,exp,colon
,code) ->
858 let exp = expression exp in
859 let code = dots is_stm_dots (Some
(promote_mcode colon
)) statement code in
860 mkres c
(Ast0.Case
(case
,exp,colon
,code)) (promote_mcode case
) code
861 | Ast0.DisjCase
(starter,case_lines
,mids,ender) ->
862 let starter = bad_mcode starter in
863 let case_lines = List.map case_line
case_lines in
864 let mids = List.map
bad_mcode mids in
865 let ender = bad_mcode ender in
866 mkmultires c
(Ast0.DisjCase
(starter,case_lines,mids,ender))
867 (promote_mcode starter) (promote_mcode ender)
868 (get_all_start_info case_lines) (get_all_end_info case_lines)
869 | Ast0.OptCase
(case
) ->
870 let case = case_line
case in mkres c
(Ast0.OptCase
(case)) case case
872 and statement_dots x
= dots is_stm_dots None
statement x
874 (* --------------------------------------------------------------------- *)
875 (* Function declaration *)
878 match Ast0.unwrap t
with
879 Ast0.FILEINFO
(old_file
,new_file
) -> t
881 let stmt = statement stmt in mkres t
(Ast0.DECL
(stmt)) stmt stmt
882 | Ast0.CODE
(rule_elem_dots) ->
883 let rule_elem_dots = dots is_stm_dots None
statement rule_elem_dots in
884 mkres t
(Ast0.CODE
(rule_elem_dots)) rule_elem_dots rule_elem_dots
885 | Ast0.ERRORWORDS
(exps) -> t
886 | Ast0.OTHER
(_
) -> failwith
"eliminated by top_level"
888 (* --------------------------------------------------------------------- *)
891 let compute_lines attachable_or x
=
893 inherit_attachable := attachable_or
;
896 let compute_statement_lines attachable_or x
=
898 inherit_attachable := attachable_or
;
901 let compute_statement_dots_lines attachable_or x
=
903 inherit_attachable := attachable_or
;