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 (* Arities matter for the minus slice, but not for the plus slice. *)
47 (* + only allowed on code in a nest (in_nest = true). ? only allowed on
48 rule_elems, and on subterms if the context is ? also. *)
50 module Ast0
= Ast0_cocci
51 module Ast
= Ast_cocci
52 module V0
= Visitor_ast0
53 module VT0
= Visitor_ast0_types
54 module V
= Visitor_ast
56 let unitary = Type_cocci.Unitary
64 (* --------------------------------------------------------------------- *)
65 (* Move plus tokens from the MINUS and CONTEXT structured nodes to the
66 corresponding leftmost and rightmost mcodes *)
70 let option_default = () in
72 let do_nothing r k e
=
74 let einfo = Ast0.get_info e
in
75 match (Ast0.get_mcodekind e
) with
76 Ast0.MINUS
(replacements
) ->
77 (match !replacements
with
80 let minus_try = function
84 Ast0.MINUS
(mreplacements
) -> true | _
-> false)
89 Ast0.MINUS
(mreplacements
) ->
90 mreplacements
:= replacements
96 if not
(minus_try(einfo.Ast0.attachable_start
,
97 einfo.Ast0.mcode_start
)
99 minus_try(einfo.Ast0.attachable_end
,
100 einfo.Ast0.mcode_end
))
102 failwith
"minus tree should not have bad code on both sides")
103 | Ast0.CONTEXT
(befaft
)
104 | Ast0.MIXED
(befaft
) ->
105 let concat starter startinfo ender endinfo
=
107 match (starter
,ender
) with
111 if startinfo
.Ast0.tline_end
= endinfo
.Ast0.tline_start
112 then (* put them in the same inner list *)
113 let last = List.hd
(List.rev starter
) in
114 let butlast = List.rev
(List.tl
(List.rev starter
)) in
115 butlast @ (last@(List.hd ender
)) :: (List.tl ender
)
116 else starter
@ ender
in
118 {endinfo
with Ast0.tline_start
= startinfo
.Ast0.tline_start
}) in
119 let attach_bef bef beforeinfo befit
= function
123 Ast0.MINUS
(mreplacements
) ->
124 let (mrepl
,tokeninfo
) = !mreplacements
in
125 mreplacements
:= concat bef beforeinfo mrepl tokeninfo
126 | Ast0.CONTEXT
(mbefaft
) ->
128 (Ast.BEFORE
(mbef
,it
),mbeforeinfo
,a
) ->
129 let (newbef
,newinfo
) =
130 concat bef beforeinfo mbef mbeforeinfo
in
131 let it = Ast.lub_count befit
it in
132 mbefaft
:= (Ast.BEFORE
(newbef
,it),newinfo
,a
)
133 | (Ast.AFTER
(maft
,it),_
,a
) ->
134 let it = Ast.lub_count befit
it in
136 (Ast.BEFOREAFTER
(bef
,maft
,it),beforeinfo
,a
)
137 | (Ast.BEFOREAFTER
(mbef
,maft
,it),mbeforeinfo
,a
) ->
138 let (newbef
,newinfo
) =
139 concat bef beforeinfo mbef mbeforeinfo
in
140 let it = Ast.lub_count befit
it in
142 (Ast.BEFOREAFTER
(newbef
,maft
,it),newinfo
,a
)
143 | (Ast.NOTHING
,_
,a
) ->
145 (Ast.BEFORE
(bef
,befit
),beforeinfo
,a
))
146 | _
-> failwith
"unexpected annotation")
149 Printf.printf
"before %s\n" (Dumper.dump bef
);
151 "context tree should not have bad code before" in
152 let attach_aft aft afterinfo aftit
= function
156 Ast0.MINUS
(mreplacements
) ->
157 let (mrepl
,tokeninfo
) = !mreplacements
in
158 mreplacements
:= concat mrepl tokeninfo aft afterinfo
159 | Ast0.CONTEXT
(mbefaft
) ->
161 (Ast.BEFORE
(mbef
,it),b
,_
) ->
162 let it = Ast.lub_count aftit
it in
164 (Ast.BEFOREAFTER
(mbef
,aft
,it),b
,afterinfo
)
165 | (Ast.AFTER
(maft
,it),b
,mafterinfo
) ->
166 let (newaft
,newinfo
) =
167 concat maft mafterinfo aft afterinfo
in
168 let it = Ast.lub_count aftit
it in
169 mbefaft
:= (Ast.AFTER
(newaft
,it),b
,newinfo
)
170 | (Ast.BEFOREAFTER
(mbef
,maft
,it),b
,mafterinfo
) ->
171 let (newaft
,newinfo
) =
172 concat maft mafterinfo aft afterinfo
in
173 let it = Ast.lub_count aftit
it in
175 (Ast.BEFOREAFTER
(mbef
,newaft
,it),b
,newinfo
)
176 | (Ast.NOTHING
,b
,_
) ->
177 mbefaft
:= (Ast.AFTER
(aft
,aftit
),b
,afterinfo
))
178 | _
-> failwith
"unexpected annotation")
182 "context tree should not have bad code after" in
184 (Ast.BEFORE
(bef
,it),beforeinfo
,_
) ->
185 attach_bef bef beforeinfo
it
186 (einfo.Ast0.attachable_start
,einfo.Ast0.mcode_start
)
187 | (Ast.AFTER
(aft
,it),_
,afterinfo
) ->
188 attach_aft aft afterinfo
it
189 (einfo.Ast0.attachable_end
,einfo.Ast0.mcode_end
)
190 | (Ast.BEFOREAFTER
(bef
,aft
,it),beforeinfo
,afterinfo
) ->
191 attach_bef bef beforeinfo
it
192 (einfo.Ast0.attachable_start
,einfo.Ast0.mcode_start
);
193 attach_aft aft afterinfo
it
194 (einfo.Ast0.attachable_end
,einfo.Ast0.mcode_end
)
195 | (Ast.NOTHING
,_
,_
) -> ())
196 | Ast0.PLUS _
-> () in
197 V0.flat_combiner
bind option_default
198 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
200 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
201 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
202 do_nothing do_nothing do_nothing
204 (* --------------------------------------------------------------------- *)
205 (* For function declarations. Can't use the mcode at the root, because that
206 might be mixed when the function contains ()s, where agglomeration of -s is
210 let donothing r k e
= k e
in
211 let bind x y
= x
&& y
in
212 let option_default = true in
213 let mcode (_
,_
,_
,mc
,_
,_
) =
215 Ast0.MINUS
(r
) -> let (plusses
,_
) = !r
in plusses
= []
218 (* special case for disj *)
219 let expression r k e
=
220 match Ast0.unwrap e
with
221 Ast0.DisjExpr
(starter
,expr_list
,mids
,ender
) ->
222 List.for_all r
.VT0.combiner_rec_expression expr_list
225 let declaration r k e
=
226 match Ast0.unwrap e
with
227 Ast0.DisjDecl
(starter
,decls
,mids
,ender
) ->
228 List.for_all r
.VT0.combiner_rec_declaration decls
232 match Ast0.unwrap e
with
233 Ast0.DisjType
(starter
,decls
,mids
,ender
) ->
234 List.for_all r
.VT0.combiner_rec_typeC decls
237 let statement r k e
=
238 match Ast0.unwrap e
with
239 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
240 List.for_all r
.VT0.combiner_rec_statement_dots statement_dots_list
243 let case_line r k e
=
244 match Ast0.unwrap e
with
245 Ast0.DisjCase
(starter
,case_lines
,mids
,ender
) ->
246 List.for_all r
.VT0.combiner_rec_case_line case_lines
249 V0.flat_combiner
bind option_default
250 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
252 donothing donothing donothing donothing donothing donothing
253 donothing expression typeC donothing donothing declaration
254 statement case_line donothing
256 (* --------------------------------------------------------------------- *)
257 (* --------------------------------------------------------------------- *)
259 let get_option fn
= function
261 | Some x
-> Some
(fn x
)
263 (* --------------------------------------------------------------------- *)
264 (* --------------------------------------------------------------------- *)
267 let convert_info info
=
270 (function (s
,info
) -> (s
,info
.Ast0.line_start
,info
.Ast0.column
))
272 { Ast.line
= info
.Ast0.pos_info
.Ast0.line_start
;
273 Ast.column
= info
.Ast0.pos_info
.Ast0.column
;
274 Ast.strbef
= strings_to_s info
.Ast0.strings_before
;
275 Ast.straft
= strings_to_s info
.Ast0.strings_after
;}
277 let convert_mcodekind adj
= function
278 Ast0.MINUS
(replacements
) ->
279 let (replacements
,_
) = !replacements
in
280 Ast.MINUS
(Ast.NoPos
,[],adj
,replacements
)
281 | Ast0.PLUS count
-> Ast.PLUS count
282 | Ast0.CONTEXT
(befaft
) ->
283 let (befaft
,_
,_
) = !befaft
in Ast.CONTEXT
(Ast.NoPos
,befaft
)
284 | Ast0.MIXED
(_
) -> failwith
"not possible for mcode"
286 let pos_mcode(term
,_
,info
,mcodekind
,pos
,adj
) =
287 (* avoids a recursion problem *)
288 (term
,convert_info info
,convert_mcodekind adj mcodekind
,Ast.NoMetaPos
)
290 let mcode (term
,_
,info
,mcodekind
,pos
,adj
) =
293 Ast0.MetaPos
(pos,constraints
,per
) ->
294 Ast.MetaPos
(pos_mcode pos,constraints
,per
,unitary,false)
295 | _
-> Ast.NoMetaPos
in
296 (term
,convert_info info
,convert_mcodekind adj mcodekind
,pos)
298 (* --------------------------------------------------------------------- *)
300 let wrap ast line isos
=
301 {(Ast.make_term ast
) with Ast.node_line
= line
;
304 let rewrap ast0 isos ast
=
305 wrap ast
((Ast0.get_info ast0
).Ast0.pos_info
.Ast0.line_start
) isos
309 (* no isos on tokens *)
310 let tokenwrap (_
,info
,_
,_
) s ast
= wrap ast info
.Ast.line
no_isos
311 let iso_tokenwrap (_
,info
,_
,_
) s ast iso
= wrap ast info
.Ast.line iso
315 (match Ast0.unwrap d
with
316 Ast0.DOTS
(x
) -> Ast.DOTS
(List.map fn x
)
317 | Ast0.CIRCLES
(x
) -> Ast.CIRCLES
(List.map fn x
)
318 | Ast0.STARS
(x
) -> Ast.STARS
(List.map fn x
))
320 (* --------------------------------------------------------------------- *)
323 let rec do_isos l
= List.map
(function (nm
,x
) -> (nm
,anything x
)) l
326 rewrap i
(do_isos (Ast0.get_iso i
))
327 (match Ast0.unwrap i
with
328 Ast0.Id
(name
) -> Ast.Id
(mcode name
)
329 | Ast0.MetaId
(name
,constraints
,_
) ->
330 Ast.MetaId
(mcode name
,constraints
,unitary,false)
331 | Ast0.MetaFunc
(name
,constraints
,_
) ->
332 Ast.MetaFunc
(mcode name
,constraints
,unitary,false)
333 | Ast0.MetaLocalFunc
(name
,constraints
,_
) ->
334 Ast.MetaLocalFunc
(mcode name
,constraints
,unitary,false)
335 | Ast0.OptIdent
(id
) -> Ast.OptIdent
(ident id
)
336 | Ast0.UniqueIdent
(id
) -> Ast.UniqueIdent
(ident id
))
338 (* --------------------------------------------------------------------- *)
343 rewrap e
(do_isos (Ast0.get_iso e
))
344 (match Ast0.unwrap e
with
345 Ast0.Ident
(id
) -> Ast.Ident
(ident id
)
346 | Ast0.Constant
(const
) ->
347 Ast.Constant
(mcode const
)
348 | Ast0.FunCall
(fn
,lp
,args
,rp
) ->
349 let fn = expression fn in
351 let args = dots expression args in
353 Ast.FunCall
(fn,lp,args,rp)
354 | Ast0.Assignment
(left
,op
,right
,simple
) ->
355 Ast.Assignment
(expression left
,mcode op
,expression right
,simple
)
356 | Ast0.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) ->
357 let exp1 = expression exp1 in
358 let why = mcode why in
359 let exp2 = get_option expression exp2 in
360 let colon = mcode colon in
361 let exp3 = expression exp3 in
362 Ast.CondExpr
(exp1,why,exp2,colon,exp3)
363 | Ast0.Postfix
(exp
,op
) ->
364 Ast.Postfix
(expression exp
,mcode op
)
365 | Ast0.Infix
(exp
,op
) ->
366 Ast.Infix
(expression exp
,mcode op
)
367 | Ast0.Unary
(exp
,op
) ->
368 Ast.Unary
(expression exp
,mcode op
)
369 | Ast0.Binary
(left
,op
,right
) ->
370 Ast.Binary
(expression left
,mcode op
,expression right
)
371 | Ast0.Nested
(left
,op
,right
) ->
372 Ast.Nested
(expression left
,mcode op
,expression right
)
373 | Ast0.Paren
(lp,exp
,rp) ->
374 Ast.Paren
(mcode lp,expression exp
,mcode rp)
375 | Ast0.ArrayAccess
(exp1,lb
,exp2,rb
) ->
376 Ast.ArrayAccess
(expression exp1,mcode lb
,expression exp2,mcode rb
)
377 | Ast0.RecordAccess
(exp
,pt
,field
) ->
378 Ast.RecordAccess
(expression exp
,mcode pt
,ident field
)
379 | Ast0.RecordPtAccess
(exp
,ar
,field
) ->
380 Ast.RecordPtAccess
(expression exp
,mcode ar
,ident field
)
381 | Ast0.Cast
(lp,ty
,rp,exp
) ->
382 Ast.Cast
(mcode lp,typeC ty
,mcode rp,expression exp
)
383 | Ast0.SizeOfExpr
(szf
,exp
) ->
384 Ast.SizeOfExpr
(mcode szf
,expression exp
)
385 | Ast0.SizeOfType
(szf
,lp,ty
,rp) ->
386 Ast.SizeOfType
(mcode szf
, mcode lp,typeC ty
,mcode rp)
387 | Ast0.TypeExp
(ty
) -> Ast.TypeExp
(typeC ty
)
388 | Ast0.MetaErr
(name
,cstrts
,_
) ->
389 Ast.MetaErr
(mcode name
,constraints cstrts
,unitary,false)
390 | Ast0.MetaExpr
(name
,cstrts
,ty
,form
,_
) ->
391 Ast.MetaExpr
(mcode name
,constraints cstrts
,unitary,ty
,form
,false)
392 | Ast0.MetaExprList
(name
,Some lenname
,_
) ->
393 Ast.MetaExprList
(mcode name
,Some
(mcode lenname
,unitary,false),
395 | Ast0.MetaExprList
(name
,None
,_
) ->
396 Ast.MetaExprList
(mcode name
,None
,unitary,false)
397 | Ast0.EComma
(cm
) -> Ast.EComma
(mcode cm
)
398 | Ast0.DisjExpr
(_
,exps
,_
,_
) ->
399 Ast.DisjExpr
(List.map
expression exps
)
400 | Ast0.NestExpr
(starter
,exp_dots
,ender
,whencode
,multi
) ->
401 let starter = mcode starter in
402 let whencode = get_option expression whencode in
403 let ender = mcode ender in
404 Ast.NestExpr
(starter,dots expression exp_dots
,ender,whencode,multi
)
405 | Ast0.Edots
(dots,whencode) ->
406 let dots = mcode dots in
407 let whencode = get_option expression whencode in
408 Ast.Edots
(dots,whencode)
409 | Ast0.Ecircles
(dots,whencode) ->
410 let dots = mcode dots in
411 let whencode = get_option expression whencode in
412 Ast.Ecircles
(dots,whencode)
413 | Ast0.Estars
(dots,whencode) ->
414 let dots = mcode dots in
415 let whencode = get_option expression whencode in
416 Ast.Estars
(dots,whencode)
417 | Ast0.OptExp
(exp
) -> Ast.OptExp
(expression exp
)
418 | Ast0.UniqueExp
(exp
) -> Ast.UniqueExp
(expression exp
)) in
419 if Ast0.get_test_exp e
then Ast.set_test_exp
e1 else e1
421 and expression_dots ed
= dots expression ed
425 Ast0.NoConstraint
-> Ast.NoConstraint
426 | Ast0.NotIdCstrt idctrt
-> Ast.NotIdCstrt idctrt
427 | Ast0.NotExpCstrt exps
-> Ast.NotExpCstrt
(List.map
expression exps
)
428 | Ast0.SubExpCstrt ids
-> Ast.SubExpCstrt ids
430 (* --------------------------------------------------------------------- *)
433 and rewrap_iso t t1
= rewrap t
(do_isos (Ast0.get_iso t
)) t1
436 rewrap t
(do_isos (Ast0.get_iso t
))
437 (match Ast0.unwrap t
with
438 Ast0.ConstVol
(cv
,ty
) ->
439 let rec collect_disjs t
=
440 match Ast0.unwrap t
with
441 Ast0.DisjType
(_
,types
,_
,_
) ->
442 if Ast0.get_iso t
= []
443 then List.concat (List.map
collect_disjs types
)
444 else failwith
"unexpected iso on a disjtype"
450 (Some
(mcode cv
),rewrap_iso ty
(base_typeC ty
)))
451 (collect_disjs ty
) in
452 (* one could worry that isos are lost because we flatten the
453 disjunctions. but there should not be isos on the disjunctions
457 | types
-> Ast.DisjType
(List.map
(rewrap t
no_isos) types
))
458 | Ast0.BaseType
(_
) | Ast0.Signed
(_
,_
) | Ast0.Pointer
(_
,_
)
459 | Ast0.FunctionPointer
(_
,_
,_
,_
,_
,_
,_
) | Ast0.FunctionType
(_
,_
,_
,_
)
460 | Ast0.Array
(_
,_
,_
,_
) | Ast0.EnumName
(_
,_
) | Ast0.StructUnionName
(_
,_
)
461 | Ast0.StructUnionDef
(_
,_
,_
,_
) | Ast0.TypeName
(_
) | Ast0.MetaType
(_
,_
) ->
462 Ast.Type
(None
,rewrap t
no_isos (base_typeC t
))
463 | Ast0.DisjType
(_
,types
,_
,_
) -> Ast.DisjType
(List.map
typeC types
)
464 | Ast0.OptType
(ty
) -> Ast.OptType
(typeC ty
)
465 | Ast0.UniqueType
(ty
) -> Ast.UniqueType
(typeC ty
))
468 match Ast0.unwrap t
with
469 Ast0.BaseType
(ty
,strings
) -> Ast.BaseType
(ty
,List.map
mcode strings
)
470 | Ast0.Signed
(sgn
,ty
) ->
471 Ast.SignedT
(mcode sgn
,
472 get_option (function x
-> rewrap_iso x
(base_typeC x
)) ty
)
473 | Ast0.Pointer
(ty
,star
) -> Ast.Pointer
(typeC ty
,mcode star
)
474 | Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) ->
476 (typeC ty
,mcode lp1
,mcode star
,mcode rp1
,
477 mcode lp2
,parameter_list params
,mcode rp2
)
478 | Ast0.FunctionType
(ret
,lp,params
,rp) ->
479 let allminus = check_allminus.VT0.combiner_rec_typeC t
in
481 (allminus,get_option typeC ret
,mcode lp,
482 parameter_list params
,mcode rp)
483 | Ast0.Array
(ty
,lb
,size
,rb
) ->
484 Ast.Array
(typeC ty
,mcode lb
,get_option expression size
,mcode rb
)
485 | Ast0.EnumName
(kind
,name
) ->
486 Ast.EnumName
(mcode kind
,ident name
)
487 | Ast0.StructUnionName
(kind
,name
) ->
488 Ast.StructUnionName
(mcode kind
,get_option ident name
)
489 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) ->
490 Ast.StructUnionDef
(typeC ty
,mcode lb
,
491 dots declaration decls
,
493 | Ast0.TypeName
(name
) -> Ast.TypeName
(mcode name
)
494 | Ast0.MetaType
(name
,_
) ->
495 Ast.MetaType
(mcode name
,unitary,false)
496 | _
-> failwith
"ast0toast: unexpected type"
498 (* --------------------------------------------------------------------- *)
499 (* Variable declaration *)
500 (* Even if the Cocci program specifies a list of declarations, they are
501 split out into multiple declarations of a single variable each. *)
504 rewrap d
(do_isos (Ast0.get_iso d
))
505 (match Ast0.unwrap d
with
506 Ast0.Init
(stg
,ty
,id
,eq
,ini
,sem
) ->
507 let stg = get_option mcode stg in
511 let ini = initialiser
ini in
512 let sem = mcode sem in
513 Ast.Init
(stg,ty,id,eq,ini,sem)
514 | Ast0.UnInit
(stg,ty,id,sem) ->
515 (match Ast0.unwrap
ty with
516 Ast0.FunctionType
(tyx
,lp1
,params
,rp1
) ->
517 let allminus = check_allminus.VT0.combiner_rec_declaration d
in
518 Ast.UnInit
(get_option mcode stg,
519 rewrap ty (do_isos (Ast0.get_iso
ty))
524 (allminus,get_option typeC tyx
,mcode lp1
,
525 parameter_list params
,mcode rp1
)))),
527 | _
-> Ast.UnInit
(get_option mcode stg,typeC ty,ident
id,mcode sem))
528 | Ast0.MacroDecl
(name
,lp,args,rp,sem) ->
529 let name = ident
name in
531 let args = dots expression args in
533 let sem = mcode sem in
534 Ast.MacroDecl
(name,lp,args,rp,sem)
535 | Ast0.TyDecl
(ty,sem) -> Ast.TyDecl
(typeC ty,mcode sem)
536 | Ast0.Typedef
(stg,ty,id,sem) ->
538 (match Ast.unwrap
id with
539 Ast.Type
(None
,id) -> (* only MetaType or Id *)
540 Ast.Typedef
(mcode stg,typeC ty,id,mcode sem)
541 | _
-> failwith
"bad typedef")
542 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> Ast.DisjDecl
(List.map
declaration decls
)
543 | Ast0.Ddots
(dots,whencode) ->
544 let dots = mcode dots in
545 let whencode = get_option declaration whencode in
546 Ast.Ddots
(dots,whencode)
547 | Ast0.OptDecl
(decl
) -> Ast.OptDecl
(declaration decl
)
548 | Ast0.UniqueDecl
(decl
) -> Ast.UniqueDecl
(declaration decl
))
550 and declaration_dots l
= dots declaration l
552 (* --------------------------------------------------------------------- *)
555 and strip_idots initlist
=
556 match Ast0.unwrap initlist
with
558 let (whencode,init
) =
560 (function (prevwhen
,previnit
) ->
562 match Ast0.unwrap cur
with
563 Ast0.Idots
(dots,Some
whencode) ->
564 (whencode :: prevwhen
, previnit
)
565 | Ast0.Idots
(dots,None
) -> (prevwhen
,previnit
)
566 | _
-> (prevwhen
, cur
:: previnit
))
568 (List.rev
whencode, List.rev init
)
569 | Ast0.CIRCLES
(x
) | Ast0.STARS
(x
) -> failwith
"not possible for an initlist"
573 (match Ast0.unwrap i
with
574 Ast0.MetaInit
(name,_
) -> Ast.MetaInit
(mcode name,unitary,false)
575 | Ast0.InitExpr
(exp
) -> Ast.InitExpr
(expression exp
)
576 | Ast0.InitList
(lb
,initlist
,rb
) ->
577 let (whencode,initlist
) = strip_idots initlist
in
578 Ast.InitList
(mcode lb
,List.map initialiser initlist
,mcode rb
,
579 List.map initialiser
whencode)
580 | Ast0.InitGccExt
(designators
,eq,ini) ->
581 Ast.InitGccExt
(List.map designator designators
,mcode eq,
583 | Ast0.InitGccName
(name,eq,ini) ->
584 Ast.InitGccName
(ident
name,mcode eq,initialiser
ini)
585 | Ast0.IComma
(comma
) -> Ast.IComma
(mcode comma
)
586 | Ast0.Idots
(_
,_
) -> failwith
"Idots should have been removed"
587 | Ast0.OptIni
(ini) -> Ast.OptIni
(initialiser
ini)
588 | Ast0.UniqueIni
(ini) -> Ast.UniqueIni
(initialiser
ini))
590 and designator
= function
591 Ast0.DesignatorField
(dot
,id) -> Ast.DesignatorField
(mcode dot
,ident
id)
592 | Ast0.DesignatorIndex
(lb
,exp
,rb
) ->
593 Ast.DesignatorIndex
(mcode lb
, expression exp
, mcode rb
)
594 | Ast0.DesignatorRange
(lb
,min
,dots,max
,rb
) ->
595 Ast.DesignatorRange
(mcode lb
,expression min
,mcode dots,expression max
,
598 (* --------------------------------------------------------------------- *)
601 and parameterTypeDef p
=
603 (match Ast0.unwrap p
with
604 Ast0.VoidParam
(ty) -> Ast.VoidParam
(typeC ty)
605 | Ast0.Param
(ty,id) -> Ast.Param
(typeC ty,get_option ident
id)
606 | Ast0.MetaParam
(name,_
) ->
607 Ast.MetaParam
(mcode name,unitary,false)
608 | Ast0.MetaParamList
(name,Some lenname
,_
) ->
609 Ast.MetaParamList
(mcode name,Some
(mcode lenname
,unitary,false),
611 | Ast0.MetaParamList
(name,None
,_
) ->
612 Ast.MetaParamList
(mcode name,None
,unitary,false)
613 | Ast0.PComma
(cm
) -> Ast.PComma
(mcode cm
)
614 | Ast0.Pdots
(dots) -> Ast.Pdots
(mcode dots)
615 | Ast0.Pcircles
(dots) -> Ast.Pcircles
(mcode dots)
616 | Ast0.OptParam
(param
) -> Ast.OptParam
(parameterTypeDef param
)
617 | Ast0.UniqueParam
(param
) -> Ast.UniqueParam
(parameterTypeDef param
))
619 and parameter_list l
= dots parameterTypeDef l
621 (* --------------------------------------------------------------------- *)
625 let rec statement seqible s
=
626 let rewrap_stmt ast0 ast
=
628 match Ast0.get_dots_bef_aft s
with
629 Ast0.NoDots
-> Ast.NoDots
630 | Ast0.DroppingBetweenDots s
->
631 Ast.DroppingBetweenDots
(statement seqible s
,get_ctr())
632 | Ast0.AddingBetweenDots s
->
633 Ast.AddingBetweenDots
(statement seqible s
,get_ctr()) in
634 Ast.set_dots_bef_aft
befaft (rewrap ast0
no_isos ast
) in
635 let rewrap_rule_elem ast0 ast
=
636 rewrap ast0
(do_isos (Ast0.get_iso ast0
)) ast
in
638 (match Ast0.unwrap s
with
639 Ast0.Decl
((_
,bef
),decl
) ->
640 Ast.Atomic
(rewrap_rule_elem s
641 (Ast.Decl
(convert_mcodekind (-1) bef
,
642 check_allminus.VT0.combiner_rec_statement s
,
644 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
645 let lbrace = mcode lbrace in
646 let body = dots (statement seqible
) body in
647 let rbrace = mcode rbrace in
648 Ast.Seq
(iso_tokenwrap lbrace s
(Ast.SeqStart
(lbrace))
649 (do_isos (Ast0.get_iso s
)),
651 tokenwrap rbrace s
(Ast.SeqEnd
(rbrace)))
652 | Ast0.ExprStatement
(exp
,sem) ->
653 Ast.Atomic
(rewrap_rule_elem s
654 (Ast.ExprStatement
(expression exp
,mcode sem)))
655 | Ast0.IfThen
(iff
,lp,exp
,rp,branch
,(_
,aft
)) ->
658 (Ast.IfHeader
(mcode iff
,mcode lp,expression exp
,mcode rp)),
659 statement Ast.NotSequencible branch
,
660 ([],[],[],convert_mcodekind (-1) aft
))
661 | Ast0.IfThenElse
(iff
,lp,exp
,rp,branch1
,els
,branch2
,(_
,aft
)) ->
662 let els = mcode els in
665 (Ast.IfHeader
(mcode iff
,mcode lp,expression exp
,mcode rp)),
666 statement Ast.NotSequencible branch1
,
667 tokenwrap els s
(Ast.Else
(els)),
668 statement Ast.NotSequencible branch2
,
669 ([],[],[],convert_mcodekind (-1) aft
))
670 | Ast0.While
(wh
,lp,exp
,rp,body,(_
,aft
)) ->
671 Ast.While
(rewrap_rule_elem s
673 (mcode wh
,mcode lp,expression exp
,mcode rp)),
674 statement Ast.NotSequencible
body,
675 ([],[],[],convert_mcodekind (-1) aft
))
676 | Ast0.Do
(d
,body,wh
,lp,exp
,rp,sem) ->
678 Ast.Do
(rewrap_rule_elem s
(Ast.DoHeader
(mcode d
)),
679 statement Ast.NotSequencible
body,
681 (Ast.WhileTail
(wh,mcode lp,expression exp
,mcode rp,
683 | Ast0.For
(fr
,lp,exp1,sem1
,exp2,sem2
,exp3,rp,body,(_
,aft
)) ->
686 let exp1 = get_option expression exp1 in
687 let sem1 = mcode sem1 in
688 let exp2 = get_option expression exp2 in
689 let sem2= mcode sem2 in
690 let exp3 = get_option expression exp3 in
692 let body = statement Ast.NotSequencible
body in
693 Ast.For
(rewrap_rule_elem s
694 (Ast.ForHeader
(fr,lp,exp1,sem1,exp2,sem2,exp3,rp)),
695 body,([],[],[],convert_mcodekind (-1) aft
))
696 | Ast0.Iterator
(nm
,lp,args,rp,body,(_
,aft
)) ->
697 Ast.Iterator
(rewrap_rule_elem s
700 dots expression args,
702 statement Ast.NotSequencible
body,
703 ([],[],[],convert_mcodekind (-1) aft
))
704 | Ast0.Switch
(switch
,lp,exp
,rp,lb
,decls
,cases
,rb
) ->
705 let switch = mcode switch in
707 let exp = expression exp in
710 let decls = dots (statement seqible
) decls in
711 let cases = List.map
case_line (Ast0.undots
cases) in
713 Ast.Switch
(rewrap_rule_elem s
(Ast.SwitchHeader
(switch,lp,exp,rp)),
714 tokenwrap lb s
(Ast.SeqStart
(lb)),
716 tokenwrap rb s
(Ast.SeqEnd
(rb)))
717 | Ast0.Break
(br
,sem) ->
718 Ast.Atomic
(rewrap_rule_elem s
(Ast.Break
(mcode br
,mcode sem)))
719 | Ast0.Continue
(cont
,sem) ->
720 Ast.Atomic
(rewrap_rule_elem s
(Ast.Continue
(mcode cont
,mcode sem)))
721 | Ast0.Label
(l
,dd
) ->
722 Ast.Atomic
(rewrap_rule_elem s
(Ast.Label
(ident l
,mcode dd
)))
723 | Ast0.Goto
(goto
,l
,sem) ->
725 (rewrap_rule_elem s
(Ast.Goto
(mcode goto
,ident l
,mcode sem)))
726 | Ast0.Return
(ret
,sem) ->
727 Ast.Atomic
(rewrap_rule_elem s
(Ast.Return
(mcode ret
,mcode sem)))
728 | Ast0.ReturnExpr
(ret
,exp,sem) ->
731 (Ast.ReturnExpr
(mcode ret
,expression exp,mcode sem)))
732 | Ast0.MetaStmt
(name,_
) ->
733 Ast.Atomic
(rewrap_rule_elem s
734 (Ast.MetaStmt
(mcode name,unitary,seqible
,false)))
735 | Ast0.MetaStmtList
(name,_
) ->
736 Ast.Atomic
(rewrap_rule_elem s
737 (Ast.MetaStmtList
(mcode name,unitary,false)))
738 | Ast0.TopExp
(exp) ->
739 Ast.Atomic
(rewrap_rule_elem s
(Ast.TopExp
(expression exp)))
741 Ast.Atomic
(rewrap_rule_elem s
(Ast.Exp
(expression exp)))
742 | Ast0.TopInit
(init
) ->
743 Ast.Atomic
(rewrap_rule_elem s
(Ast.TopInit
(initialiser init
)))
745 Ast.Atomic
(rewrap_rule_elem s
(Ast.Ty
(typeC ty)))
746 | Ast0.Disj
(_
,rule_elem_dots_list
,_
,_
) ->
747 Ast.Disj
(List.map
(function x
-> statement_dots seqible x
)
749 | Ast0.Nest
(starter,rule_elem_dots
,ender,whn
,multi
) ->
751 (mcode starter,statement_dots
Ast.Sequencible rule_elem_dots
,
754 (whencode (statement_dots
Ast.Sequencible
)
755 (statement Ast.NotSequencible
))
758 | Ast0.Dots
(d
,whn
) ->
762 (whencode (statement_dots
Ast.Sequencible
)
763 (statement Ast.NotSequencible
))
765 Ast.Dots
(d,whn,[],[])
766 | Ast0.Circles
(d,whn) ->
770 (whencode (statement_dots
Ast.Sequencible
)
771 (statement Ast.NotSequencible
))
773 Ast.Circles
(d,whn,[],[])
774 | Ast0.Stars
(d,whn) ->
778 (whencode (statement_dots
Ast.Sequencible
)
779 (statement Ast.NotSequencible
))
781 Ast.Stars
(d,whn,[],[])
782 | Ast0.FunDecl
((_
,bef
),fi
,name,lp,params
,rp,lbrace,body,rbrace) ->
783 let fi = List.map fninfo
fi in
784 let name = ident
name in
786 let params = parameter_list
params in
788 let lbrace = mcode lbrace in
789 let body = dots (statement seqible
) body in
790 let rbrace = mcode rbrace in
791 let allminus = check_allminus.VT0.combiner_rec_statement s
in
792 Ast.FunDecl
(rewrap_rule_elem s
793 (Ast.FunHeader
(convert_mcodekind (-1) bef
,
794 allminus,fi,name,lp,params,rp)),
795 tokenwrap lbrace s
(Ast.SeqStart
(lbrace)),
797 tokenwrap rbrace s
(Ast.SeqEnd
(rbrace)))
798 | Ast0.Include
(inc
,str
) ->
799 Ast.Atomic
(rewrap_rule_elem s
(Ast.Include
(mcode inc
,mcode str
)))
800 | Ast0.Define
(def
,id,params,body) ->
804 (mcode def
,ident
id, define_parameters
params)),
805 statement_dots
Ast.NotSequencible
(*not sure*) body)
806 | Ast0.OptStm
(stm
) -> Ast.OptStm
(statement seqible stm
)
807 | Ast0.UniqueStm
(stm
) -> Ast.UniqueStm
(statement seqible stm
))
809 and define_parameters p
=
811 (match Ast0.unwrap p
with
812 Ast0.NoParams
-> Ast.NoParams
813 | Ast0.DParams
(lp,params,rp) ->
814 Ast.DParams
(mcode lp,
815 dots define_param
params,
820 (match Ast0.unwrap p
with
821 Ast0.DParam
(id) -> Ast.DParam
(ident
id)
822 | Ast0.DPComma
(comma
) -> Ast.DPComma
(mcode comma
)
823 | Ast0.DPdots
(d) -> Ast.DPdots
(mcode d)
824 | Ast0.DPcircles
(c) -> Ast.DPcircles
(mcode c)
825 | Ast0.OptDParam
(dp
) -> Ast.OptDParam
(define_param dp
)
826 | Ast0.UniqueDParam
(dp
) -> Ast.UniqueDParam
(define_param dp
))
828 and whencode notfn alwaysfn
= function
829 Ast0.WhenNot a
-> Ast.WhenNot
(notfn a
)
830 | Ast0.WhenAlways a
-> Ast.WhenAlways
(alwaysfn a
)
831 | Ast0.WhenModifier
(x
) -> Ast.WhenModifier
(x
)
833 let rewrap_rule_elem ast0 ast
=
834 rewrap ast0
(do_isos (Ast0.get_iso ast0
)) ast
in
836 Ast0.WhenNotTrue
(e
) ->
837 Ast.WhenNotTrue
(rewrap_rule_elem e
(Ast.Exp
(expression e
)))
838 | Ast0.WhenNotFalse
(e
) ->
839 Ast.WhenNotFalse
(rewrap_rule_elem e
(Ast.Exp
(expression e
)))
840 | _
-> failwith
"not possible"
842 and process_list seqible isos
= function
845 let first = statement seqible x
in
847 if !Flag.track_iso_usage
848 then Ast.set_isos
first (isos
@(Ast.get_isos
first))
850 (match Ast0.unwrap x
with
851 Ast0.Dots
(_
,_
) | Ast0.Nest
(_
) ->
852 first::(process_list
(Ast.SequencibleAfterDots
[]) no_isos rest
)
854 first::(process_list
Ast.Sequencible
no_isos rest
))
856 and statement_dots seqible
d =
857 let isos = do_isos (Ast0.get_iso
d) in
859 (match Ast0.unwrap
d with
860 Ast0.DOTS
(x
) -> Ast.DOTS
(process_list seqible
isos x
)
861 | Ast0.CIRCLES
(x
) -> Ast.CIRCLES
(process_list seqible
isos x
)
862 | Ast0.STARS
(x
) -> Ast.STARS
(process_list seqible
isos x
))
864 (* the following is no longer used.
865 the goal was to let one put a statement at the very beginning of a function
866 pattern and have it skip over the declarations in the C code.
867 that feature was removed a long time ago, however, in favor of
868 ... when != S, which also causes whatever comes after it to match the
869 first real statement.
870 the separation of declarations from the rest of the body means that the
871 quantifier of any variable shared between them comes out too high, posing
872 problems when there is ... decl ... stmt, as the quantifier of any shared
873 variable will be around the whole thing, making variables not free enough
874 in the first ..., and thus not implementing the expected shortest path
875 condition. example: f() { ... int A; ... foo(A); }.
876 the quantifier for A should start just before int A, not at the top of the
878 and separate_decls seqible d =
879 let rec collect_decls = function
882 (match Ast0.unwrap x with
884 let (decls,other) = collect_decls xs in
886 | Ast0.Dots(_,_) | Ast0.Nest(_,_,_,_,_) ->
887 let (decls,other) = collect_decls xs in
890 | _ -> (x :: decls,other))
891 | Ast0.Disj(starter,stmt_dots_list,mids,ender) ->
892 let disjs = List.map collect_dot_decls stmt_dots_list in
893 let all_decls = List.for_all (function (_,s) -> s=[]) disjs in
896 let (decls,other) = collect_decls xs in
901 and collect_dot_decls d =
902 match Ast0.unwrap d with
903 Ast0.DOTS(x) -> collect_decls x
904 | Ast0.CIRCLES(x) -> collect_decls x
905 | Ast0.STARS(x) -> collect_decls x in
908 let (decls,other) = collect_decls l in
909 (rewrap d no_isos (fn (List.map (statement seqible) decls)),
911 (fn (process_list seqible (do_isos (Ast0.get_iso d)) other))) in
912 match Ast0.unwrap d with
913 Ast0.DOTS(x) -> process x d (function x -> Ast.DOTS x)
914 | Ast0.CIRCLES(x) -> process x d (function x -> Ast.CIRCLES x)
915 | Ast0.STARS(x) -> process x d (function x -> Ast.STARS x) *) in
917 statement Ast.Sequencible s
919 and fninfo
= function
920 Ast0.FStorage
(stg) -> Ast.FStorage
(mcode stg)
921 | Ast0.FType
(ty) -> Ast.FType
(typeC ty)
922 | Ast0.FInline
(inline
) -> Ast.FInline
(mcode inline
)
923 | Ast0.FAttr
(attr
) -> Ast.FAttr
(mcode attr
)
925 and option_to_list
= function
931 (match Ast0.unwrap
c with
932 Ast0.Default
(def
,colon,code
) ->
933 let def = mcode def in
934 let colon = mcode colon in
935 let code = dots statement code in
936 Ast.CaseLine
(rewrap c no_isos (Ast.Default
(def,colon)),code)
937 | Ast0.Case
(case
,exp,colon,code) ->
938 let case = mcode case in
939 let exp = expression exp in
940 let colon = mcode colon in
941 let code = dots statement code in
942 Ast.CaseLine
(rewrap c no_isos (Ast.Case
(case,exp,colon)),code)
943 | Ast0.DisjCase
(_
,case_lines
,_
,_
) ->
944 failwith
"not supported"
945 (*Ast.CaseLine(Ast.DisjRuleElem(List.map case_line case_lines))*)
947 | Ast0.OptCase
(case) -> Ast.OptCase
(case_line case))
949 and statement_dots l
= dots statement l
951 (* --------------------------------------------------------------------- *)
953 (* what is possible is only what is at the top level in an iso *)
954 and anything
= function
955 Ast0.DotsExprTag
(d) -> Ast.ExprDotsTag
(expression_dots
d)
956 | Ast0.DotsParamTag
(d) -> Ast.ParamDotsTag
(parameter_list
d)
957 | Ast0.DotsInitTag
(d) -> failwith
"not possible"
958 | Ast0.DotsStmtTag
(d) -> Ast.StmtDotsTag
(statement_dots
d)
959 | Ast0.DotsDeclTag
(d) -> Ast.DeclDotsTag
(declaration_dots
d)
960 | Ast0.DotsCaseTag
(d) -> failwith
"not possible"
961 | Ast0.IdentTag
(d) -> Ast.IdentTag
(ident
d)
962 | Ast0.ExprTag
(d) -> Ast.ExpressionTag
(expression d)
963 | Ast0.ArgExprTag
(d) | Ast0.TestExprTag
(d) ->
964 failwith
"only in isos, not converted to ast"
965 | Ast0.TypeCTag
(d) -> Ast.FullTypeTag
(typeC d)
966 | Ast0.ParamTag
(d) -> Ast.ParamTag
(parameterTypeDef
d)
967 | Ast0.InitTag
(d) -> Ast.InitTag
(initialiser
d)
968 | Ast0.DeclTag
(d) -> Ast.DeclarationTag
(declaration d)
969 | Ast0.StmtTag
(d) -> Ast.StatementTag
(statement d)
970 | Ast0.CaseLineTag
(d) -> Ast.CaseLineTag
(case_line d)
971 | Ast0.TopTag
(d) -> Ast.Code
(top_level
d)
972 | Ast0.IsoWhenTag
(_
) -> failwith
"not possible"
973 | Ast0.IsoWhenTTag
(_
) -> failwith
"not possible"
974 | Ast0.IsoWhenFTag
(_
) -> failwith
"not possible"
975 | Ast0.MetaPosTag _
-> failwith
"not possible"
977 (* --------------------------------------------------------------------- *)
978 (* Function declaration *)
979 (* top level isos are probably lost to tracking *)
983 (match Ast0.unwrap t
with
984 Ast0.FILEINFO
(old_file
,new_file
) ->
985 Ast.FILEINFO
(mcode old_file
,mcode new_file
)
986 | Ast0.DECL
(stmt
) -> Ast.DECL
(statement stmt
)
987 | Ast0.CODE
(rule_elem_dots
) ->
988 Ast.CODE
(statement_dots rule_elem_dots
)
989 | Ast0.ERRORWORDS
(exps
) -> Ast.ERRORWORDS
(List.map
expression exps
)
990 | Ast0.OTHER
(_
) -> failwith
"eliminated by top_level")
992 (* --------------------------------------------------------------------- *)
993 (* Entry point for minus code *)
995 (* Inline_mcodes is very important - sends + code attached to the - code
996 down to the mcodes. The functions above can only be used when there is no
997 attached + code, eg in + code itself. *)
998 let ast0toast_toplevel x
=
999 inline_mcodes.VT0.combiner_rec_top_level x
;
1002 let ast0toast name deps dropped exists x is_exp ruletype
=
1003 List.iter
inline_mcodes.VT0.combiner_rec_top_level x
;
1005 (name,(deps
,dropped
,exists
),List.map top_level x
,is_exp
,ruletype
)