3 * Copyright (C) 2006, 2007, 2008, 2009 Ecole des Mines de Nantes
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License (GPL)
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * file license.txt for more details.
18 module F
= Control_flow_c
20 (*****************************************************************************)
22 (*****************************************************************************)
24 (* todo? dont go in Include. Have a visitor flag ? disable_go_include ?
25 * disable_go_type_annotation ?
28 (*****************************************************************************)
29 (* Functions to visit the Ast, and now also the CFG nodes *)
30 (*****************************************************************************)
34 * The problem is that we manipulate the AST of C programs
35 * and some of our analysis need only to specify an action for
36 * specific cases, such as the function call case, and recurse
37 * for the other cases.
38 * Here is a simplification of our AST:
43 * | Array of expression option * ctype
47 * | FunCall of expression * expression list
49 * | RecordAccess of ..
58 * What we want is really write code like
60 * let my_analysis program =
61 * analyze_all_expressions program (fun expr ->
63 * | FunCall (e, es) -> do_something()
64 * | _ -> <find_a_way_to_recurse_for_all_the_other_cases>
67 * The problem is how to write analyze_all_expressions
68 * and find_a_way_to_recurse_for_all_the_other_cases.
70 * Our solution is to mix the ideas of visitor, pattern matching,
71 * and continuation. Here is how it looks like
72 * using our hybrid-visitor API:
74 * let my_analysis program =
75 * Visitor.visit_iter program {
76 * Visitor.kexpr = (fun k e ->
78 * | FunCall (e, es) -> do_something()
83 * You can of course also give action "hooks" for
84 * kstatement, ktype, or kdeclaration. But we don't overuse
85 * visitors and so it would be stupid to provide
86 * kfunction_call, kident, kpostfix hooks as one can just
87 * use pattern matching with kexpr to achieve the same effect.
89 * Note: when want to apply recursively, always apply the continuator
90 * on the toplevel expression, otherwise may miss some intermediate steps.
93 * | FunCall (e, es) -> ...
97 * | FunCall (e, es) -> ...
98 * Visitor_c.vk_expr bigf e
101 * | FunCall (e, es) -> ...
108 * Alternatives: from the caml mailing list:
109 * "You should have a look at the Camlp4 metaprogramming facilities :
110 * http://brion.inria.fr/gallium/index.php/Camlp4MapGenerator
111 * You would write something like" :
112 * let my_analysis program =
113 * let analysis = object (self)
114 * inherit fold as super
115 * method expr = function
116 * | FunCall (e, es) -> do_something (); self
117 * | other -> super#expr other
118 * end in analysis#expr
120 * The problem is that you don't have control about what is generated
121 * and in our case we sometimes dont want to visit too much. For instance
122 * our visitor don't recurse on the type annotation of expressions
123 * Ok, this could be worked around, but the pb remains, you
124 * don't have control and at some point you may want. In the same
125 * way we want to enforce a certain order in the visit (ok this is not good,
126 * but it's convenient) of ast elements. For instance first
127 * processing the left part 'e' of a Funcall(e,es), then the arguments 'es'.
131 (* Visitor based on continuation. Cleaner than the one based on mutable
132 * pointer functions that I had before.
133 * src: based on a (vague) idea from Remy Douence.
137 * Diff with Julia's visitor ? She does:
141 * let expression r k e =
143 * ... (List.map r.V0.combiner_expression expr_list) ...
145 * let res = V0.combiner bind option_default
146 * mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
147 * donothing donothing donothing donothing
148 * ident expression typeC donothing parameter declaration statement
151 * collect_unitary_nonunitary
152 * (List.concat (List.map res.V0.combiner_top_level t))
156 * So she has to remember at which position you must put the 'expression'
157 * function. I use record which is easier.
159 * When she calls recursively, her res.V0.combiner_xxx does not take bigf
160 * in param whereas I do
161 * | F.Decl decl -> Visitor_c.vk_decl bigf decl
162 * And with the record she gets, she does not have to do my
163 * multiple defs of function such as 'let al_type = V0.vk_type_s bigf'
165 * The code of visitor.ml is cleaner with julia because mutual recursive calls
166 * are clean such as ... 'expression e' ... and not 'f (k, bigf) e'
167 * or 'vk_expr bigf e'.
169 * So it is very dual:
170 * - I give a record but then I must handle bigf.
171 * - She gets a record, and gives a list of function
176 (* old: first version (only visiting expr)
178 let (iter_expr:((expression -> unit) -> expression -> unit) -> expression -> unit)
183 | FunCall (e, es) -> f k e; List.iter (f k) es
184 | CondExpr (e1, e2, e3) -> f k e1; f k e2; f k e3
185 | Sequence (e1, e2) -> f k e1; f k e2;
186 | Assignment (e1, op, e2) -> f k e1; f k e2;
188 | Postfix (e, op) -> f k e
189 | Infix (e, op) -> f k e
190 | Unary (e, op) -> f k e
191 | Binary (e1, op, e2) -> f k e1; f k e2;
193 | ArrayAccess (e1, e2) -> f k e1; f k e2;
194 | RecordAccess (e, s) -> f k e
195 | RecordPtAccess (e, s) -> f k e
197 | SizeOfExpr e -> f k e
199 | _ -> failwith "to complete"
203 let ex1 = Sequence (Sequence (Constant (Ident "1"), Constant (Ident "2")),
204 Constant (Ident "4"))
206 iter_expr (fun k e -> match e with
207 | Constant (Ident x) -> Common.pr2 x
217 (*****************************************************************************)
218 (* Side effect style visitor *)
219 (*****************************************************************************)
221 (* Visitors for all langage concept, not just for expression.
223 * Note that I don't visit necesserally in the order of the token
224 * found in the original file. So don't assume such hypothesis!
226 * todo? parameter ? onedecl ?
230 kexpr
: (expression -> unit) * visitor_c
-> expression -> unit;
231 kstatement
: (statement
-> unit) * visitor_c
-> statement
-> unit;
232 ktype
: (fullType
-> unit) * visitor_c
-> fullType
-> unit;
234 kdecl
: (declaration
-> unit) * visitor_c
-> declaration
-> unit;
235 kdef
: (definition
-> unit) * visitor_c
-> definition
-> unit;
236 kname
: (name
-> unit) * visitor_c
-> name
-> unit;
238 kini
: (initialiser
-> unit) * visitor_c
-> initialiser
-> unit;
239 kfield
: (field
-> unit) * visitor_c
-> field
-> unit;
241 kcppdirective
: (cpp_directive
-> unit) * visitor_c
-> cpp_directive
-> unit;
242 kdefineval
: (define_val
-> unit) * visitor_c
-> define_val
-> unit;
243 kstatementseq
: (statement_sequencable
-> unit) * visitor_c
-> statement_sequencable
-> unit;
247 knode
: (F.node
-> unit) * visitor_c
-> F.node
-> unit;
249 ktoplevel
: (toplevel
-> unit) * visitor_c
-> toplevel
-> unit;
251 kinfo
: (info
-> unit) * visitor_c
-> info
-> unit;
254 let default_visitor_c =
255 { kexpr
= (fun (k,_
) e
-> k e
);
256 kstatement
= (fun (k,_
) st
-> k st
);
257 ktype
= (fun (k,_
) t
-> k t
);
258 kdecl
= (fun (k,_
) d
-> k d
);
259 kdef
= (fun (k,_
) d
-> k d
);
260 kini
= (fun (k,_
) ie
-> k ie
);
261 kname
= (fun (k,_
) x
-> k x
);
262 kinfo
= (fun (k,_
) ii
-> k ii
);
263 knode
= (fun (k,_
) n
-> k n
);
264 ktoplevel
= (fun (k,_
) p
-> k p
);
265 kcppdirective
= (fun (k,_
) p
-> k p
);
266 kdefineval
= (fun (k,_
) p
-> k p
);
267 kstatementseq
= (fun (k,_
) p
-> k p
);
268 kfield
= (fun (k,_
) p
-> k p
);
272 (* ------------------------------------------------------------------------ *)
275 let rec vk_expr = fun bigf expr
->
276 let iif ii
= vk_ii bigf ii
in
278 let rec exprf e
= bigf
.kexpr
(k,bigf
) e
279 (* !!! dont go in _typ !!! *)
280 and k ((e
,_typ
), ii
) =
283 | Ident
(name
) -> vk_name bigf name
287 vk_argument_list bigf es
;
288 | CondExpr
(e1
, e2
, e3
) ->
289 exprf e1
; do_option
(exprf) e2
; exprf e3
290 | Sequence
(e1
, e2
) -> exprf e1
; exprf e2
;
291 | Assignment
(e1
, op
, e2
) -> exprf e1
; exprf e2
;
293 | Postfix
(e
, op
) -> exprf e
294 | Infix
(e
, op
) -> exprf e
295 | Unary
(e
, op
) -> exprf e
296 | Binary
(e1
, op
, e2
) -> exprf e1
; exprf e2
;
298 | ArrayAccess
(e1
, e2
) -> exprf e1
; exprf e2
;
299 | RecordAccess
(e
, name
) -> exprf e
; vk_name bigf name
300 | RecordPtAccess
(e
, name
) -> exprf e
; vk_name bigf name
302 | SizeOfExpr
(e
) -> exprf e
303 | SizeOfType
(t
) -> vk_type bigf t
304 | Cast
(t
, e
) -> vk_type bigf t
; exprf e
306 (* old: | StatementExpr (((declxs, statxs), is)), is2 ->
307 * List.iter (vk_decl bigf) declxs;
308 * List.iter (vk_statement bigf) statxs
310 | StatementExpr
((statxs
, is
)) ->
312 statxs
+> List.iter
(vk_statement_sequencable bigf
);
314 | Constructor
(t
, initxs
) ->
316 initxs
+> List.iter
(fun (ini
, ii
) ->
321 | ParenExpr
(e
) -> exprf e
327 (* ------------------------------------------------------------------------ *)
328 and vk_name
= fun bigf
ident ->
329 let iif ii
= vk_ii bigf ii
in
331 let rec namef x
= bigf
.kname
(k,bigf
) x
334 | RegularName
(s
, ii
) -> iif ii
335 | CppConcatenatedName xs
->
336 xs
+> List.iter
(fun ((x
,ii1
), ii2
) ->
340 | CppVariadicName
(s
, ii
) -> iif ii
341 | CppIdentBuilder
((s
,iis
), xs
) ->
343 xs
+> List.iter
(fun ((x
,iix
), iicomma
) ->
350 (* ------------------------------------------------------------------------ *)
353 and vk_statement
= fun bigf
(st
: Ast_c.statement
) ->
354 let iif ii
= vk_ii bigf ii
in
356 let rec statf x
= bigf
.kstatement
(k,bigf
) x
358 let (unwrap_st
, ii
) = st
in
361 | Labeled
(Label
(s
, st
)) -> statf st
;
362 | Labeled
(Case
(e
, st
)) -> vk_expr bigf e
; statf st
;
363 | Labeled
(CaseRange
(e
, e2
, st
)) ->
364 vk_expr bigf e
; vk_expr bigf e2
; statf st
;
365 | Labeled
(Default st
) -> statf st
;
368 statxs
+> List.iter
(vk_statement_sequencable bigf
)
369 | ExprStatement
(eopt
) -> do_option
(vk_expr bigf
) eopt
;
371 | Selection
(If
(e
, st1
, st2
)) ->
372 vk_expr bigf e
; statf st1
; statf st2
;
373 | Selection
(Switch
(e
, st
)) ->
374 vk_expr bigf e
; statf st
;
375 | Iteration
(While
(e
, st
)) ->
376 vk_expr bigf e
; statf st
;
377 | Iteration
(DoWhile
(st
, e
)) -> statf st
; vk_expr bigf e
;
378 | Iteration
(For
((e1opt
,i1
), (e2opt
,i2
), (e3opt
,i3
), st
)) ->
379 statf (ExprStatement
(e1opt
),i1
);
380 statf (ExprStatement
(e2opt
),i2
);
381 statf (ExprStatement
(e3opt
),i3
);
384 | Iteration
(MacroIteration
(s
, es
, st
)) ->
385 vk_argument_list bigf es
;
388 | Jump
(Goto name
) -> vk_name bigf name
389 | Jump
((Continue
|Break
|Return
)) -> ()
390 | Jump
(ReturnExpr e
) -> vk_expr bigf e
;
391 | Jump
(GotoComputed e
) -> vk_expr bigf e
;
393 | Decl decl
-> vk_decl bigf decl
394 | Asm asmbody
-> vk_asmbody bigf asmbody
395 | NestedFunc def
-> vk_def bigf def
400 and vk_statement_sequencable
= fun bigf stseq
->
401 let f = bigf
.kstatementseq
in
405 | StmtElem st
-> vk_statement bigf st
406 | CppDirectiveStmt directive
->
407 vk_cpp_directive bigf directive
409 vk_ifdef_directive bigf ifdef
410 | IfdefStmt2
(ifdef
, xxs
) ->
411 ifdef
+> List.iter
(vk_ifdef_directive bigf
);
412 xxs
+> List.iter
(fun xs
->
413 xs
+> List.iter
(vk_statement_sequencable bigf
)
420 and vk_type
= fun bigf t
->
421 let iif ii
= vk_ii bigf ii
in
423 let rec typef x
= bigf
.ktype
(k, bigf
) x
426 let (unwrap_q
, iiq
) = q
in
427 let (unwrap_t
, iit
) = t
in
432 | Pointer t
-> typef t
434 do_option
(vk_expr bigf
) eopt
;
436 | FunctionType
(returnt
, paramst
) ->
439 | (ts
, (b
,iihas3dots
)) ->
441 vk_param_list bigf ts
444 | Enum
(sopt
, enumt
) ->
445 enumt
+> List.iter
(fun ((name
, eopt
), iicomma
) ->
448 eopt
+> Common.do_option
(fun (info
, e
) ->
454 | StructUnion
(sopt
, _su
, fields
) ->
455 vk_struct_fields bigf fields
457 | StructUnionName
(s
, structunion
) -> ()
460 (* dont go in _typ *)
461 | TypeName
(name
,_typ
) ->
464 | ParenType t
-> typef t
465 | TypeOfExpr e
-> vk_expr bigf e
466 | TypeOfType t
-> typef t
471 and vk_attribute
= fun bigf attr
->
472 let iif ii
= vk_ii bigf ii
in
478 (* ------------------------------------------------------------------------ *)
480 and vk_decl
= fun bigf d
->
481 let iif ii
= vk_ii bigf ii
in
483 let f = bigf
.kdecl
in
486 | DeclList
(xs
,ii
) -> xs
+> List.iter
(fun (x
,ii
) ->
490 | MacroDecl
((s
, args
),ii
) ->
492 vk_argument_list bigf args
;
496 and vk_onedecl
= fun bigf onedecl
->
497 let iif ii
= vk_ii bigf ii
in
505 attrs
+> List.iter
(vk_attribute bigf
);
506 var
+> Common.do_option
(fun (name
, iniopt
) ->
508 iniopt
+> Common.do_option
(fun (info
, ini
) ->
514 and vk_ini
= fun bigf ini
->
515 let iif ii
= vk_ii bigf ii
in
517 let rec inif x
= bigf
.kini
(k, bigf
) x
521 | InitExpr e
-> vk_expr bigf e
523 initxs
+> List.iter
(fun (ini
, ii
) ->
527 | InitDesignators
(xs
, e
) ->
528 xs
+> List.iter
(vk_designator bigf
);
531 | InitFieldOld
(s
, e
) -> inif e
532 | InitIndexOld
(e1
, e
) ->
533 vk_expr bigf e1
; inif e
539 and vk_designator
= fun bigf design
->
540 let iif ii
= vk_ii bigf ii
in
541 let (designator
, ii
) = design
in
543 match designator
with
544 | DesignatorField s
-> ()
545 | DesignatorIndex e
-> vk_expr bigf e
546 | DesignatorRange
(e1
, e2
) -> vk_expr bigf e1
; vk_expr bigf e2
549 (* ------------------------------------------------------------------------ *)
551 and vk_struct_fields
= fun bigf fields
->
552 fields
+> List.iter
(vk_struct_field bigf
);
554 and vk_struct_field
= fun bigf field
->
555 let iif ii
= vk_ii bigf ii
in
557 let f = bigf
.kfield
in
560 let (xfield
, ii
) = field
in
564 (FieldDeclList
(onefield_multivars
, iiptvirg
)) ->
565 vk_struct_fieldkinds bigf onefield_multivars
;
568 | MacroStructDeclTodo
->
569 pr2_once
"MacroStructDeclTodo";
572 | CppDirectiveStruct directive
->
573 vk_cpp_directive bigf directive
574 | IfdefStruct ifdef
->
575 vk_ifdef_directive bigf ifdef
582 and vk_struct_fieldkinds
= fun bigf onefield_multivars
->
583 let iif ii
= vk_ii bigf ii
in
584 onefield_multivars
+> List.iter
(fun (field
, iicomma
) ->
587 | Simple
(nameopt
, t
) ->
588 Common.do_option
(vk_name bigf
) nameopt
;
590 | BitField
(nameopt
, t
, info
, expr
) ->
591 Common.do_option
(vk_name bigf
) nameopt
;
597 (* ------------------------------------------------------------------------ *)
600 and vk_def
= fun bigf d
->
601 let iif ii
= vk_ii bigf ii
in
607 f_type
= (returnt
, (paramst
, (b
, iib
)));
611 f_old_c_style
= oldstyle
;
616 attrs
+> List.iter
(vk_attribute bigf
);
617 vk_type bigf returnt
;
618 paramst
+> List.iter
(fun (param
,iicomma
) ->
622 oldstyle
+> Common.do_option
(fun decls
->
623 decls
+> List.iter
(vk_decl bigf
);
626 statxs
+> List.iter
(vk_statement_sequencable bigf
)
632 and vk_toplevel
= fun bigf p
->
633 let f = bigf
.ktoplevel
in
634 let iif ii
= vk_ii bigf ii
in
637 | Declaration decl
-> (vk_decl bigf decl
)
638 | Definition def
-> (vk_def bigf def
)
639 | EmptyDef ii
-> iif ii
640 | MacroTop
(s
, xs
, ii
) ->
641 vk_argument_list bigf xs
;
644 | CppTop top
-> vk_cpp_directive bigf top
645 | IfdefTop ifdefdir
-> vk_ifdef_directive bigf ifdefdir
647 | NotParsedCorrectly ii
-> iif ii
648 | FinalDef info
-> vk_info bigf info
651 and vk_program
= fun bigf xs
->
652 xs
+> List.iter
(vk_toplevel bigf
)
654 and vk_ifdef_directive bigf directive
=
655 let iif ii
= vk_ii bigf ii
in
657 | IfdefDirective
(ifkind
, ii
) -> iif ii
660 and vk_cpp_directive bigf directive
=
661 let iif ii
= vk_ii bigf ii
in
662 let f = bigf
.kcppdirective
in
663 let rec k directive
=
665 | Include
{i_include
= (s
, ii
);
669 (* go inside ? yes, can be useful, for instance for type_annotater.
670 * The only pb may be that when we want to unparse the code we
671 * don't want to unparse the included file but the unparser
672 * and pretty_print do not use visitor_c so no problem.
675 copt
+> Common.do_option
(fun (file
, asts
) ->
678 | Define
((s
,ii
), (defkind
, defval
)) ->
680 vk_define_kind bigf defkind
;
681 vk_define_val bigf defval
684 | PragmaAndCo
(ii
) ->
686 in f (k, bigf
) directive
689 and vk_define_kind bigf defkind
=
692 | DefineFunc
(params
, ii
) ->
694 params
+> List.iter
(fun ((s
,iis
), iicomma
) ->
699 and vk_define_val bigf defval
=
700 let f = bigf
.kdefineval
in
706 | DefineStmt stmt
-> vk_statement bigf stmt
707 | DefineDoWhileZero
((stmt
, e
), ii
) ->
708 vk_statement bigf stmt
;
711 | DefineFunction def
-> vk_def bigf def
712 | DefineType ty
-> vk_type bigf ty
713 | DefineText
(s
, ii
) -> vk_ii bigf ii
715 | DefineInit ini
-> vk_ini bigf ini
718 pr2_once
"DefineTodo";
720 in f (k, bigf
) defval
725 (* ------------------------------------------------------------------------ *)
726 (* Now keep fullstatement inside the control flow node,
727 * so that can then get in a MetaStmtVar the fullstatement to later
728 * pp back when the S is in a +. But that means that
729 * Exp will match an Ifnode even if there is no such exp
730 * inside the condition of the Ifnode (because the exp may
731 * be deeper, in the then branch). So have to not visit
732 * all inside a node anymore.
734 * update: j'ai choisi d'accrocher au noeud du CFG a la
735 * fois le fullstatement et le partialstatement et appeler le
736 * visiteur que sur le partialstatement.
739 and vk_node
= fun bigf node
->
740 let iif ii
= vk_ii bigf ii
in
741 let infof info
= vk_info bigf info
in
743 let f = bigf
.knode
in
745 match F.unwrap n
with
747 | F.FunHeader
(def
) ->
748 assert(null
(fst def
).f_body
);
751 | F.Decl decl
-> vk_decl bigf decl
752 | F.ExprStatement
(st
, (eopt
, ii
)) ->
754 eopt
+> do_option
(vk_expr bigf
)
756 | F.IfHeader
(_
, (e
,ii
))
757 | F.SwitchHeader
(_
, (e
,ii
))
758 | F.WhileHeader
(_
, (e
,ii
))
759 | F.DoWhileTail
(e
,ii
) ->
763 | F.ForHeader
(_st
, (((e1opt
,i1
), (e2opt
,i2
), (e3opt
,i3
)), ii
)) ->
764 iif i1
; iif i2
; iif i3
;
766 e1opt
+> do_option
(vk_expr bigf
);
767 e2opt
+> do_option
(vk_expr bigf
);
768 e3opt
+> do_option
(vk_expr bigf
);
769 | F.MacroIterHeader
(_s
, ((s
,es
), ii
)) ->
771 vk_argument_list bigf es
;
773 | F.ReturnExpr
(_st
, (e
,ii
)) -> iif ii
; vk_expr bigf e
775 | F.Case
(_st
, (e
,ii
)) -> iif ii
; vk_expr bigf e
776 | F.CaseRange
(_st
, ((e1
, e2
),ii
)) ->
777 iif ii
; vk_expr bigf e1
; vk_expr bigf e2
782 | F.DefineExpr e
-> vk_expr bigf e
783 | F.DefineType ft
-> vk_type bigf ft
784 | F.DefineHeader
((s
,ii
), (defkind
)) ->
786 vk_define_kind bigf defkind
;
788 | F.DefineDoWhileZeroHeader
(((),ii
)) -> iif ii
790 pr2_once
"DefineTodo";
794 | F.Include
{i_include
= (s
, ii
);} -> iif ii
;
796 | F.MacroTop
(s
, args
, ii
) ->
798 vk_argument_list bigf args
800 | F.IfdefHeader
(info
) -> vk_ifdef_directive bigf info
801 | F.IfdefElse
(info
) -> vk_ifdef_directive bigf info
802 | F.IfdefEndif
(info
) -> vk_ifdef_directive bigf info
804 | F.Break
(st
,((),ii
)) -> iif ii
805 | F.Continue
(st
,((),ii
)) -> iif ii
806 | F.Default
(st
,((),ii
)) -> iif ii
807 | F.Return
(st
,((),ii
)) -> iif ii
808 | F.Goto
(st
, name
, ((),ii
)) -> vk_name bigf name
; iif ii
809 | F.Label
(st
, name
, ((),ii
)) -> vk_name bigf name
; iif ii
811 | F.DoHeader
(st
, info
) -> infof info
813 | F.Else info
-> infof info
814 | F.EndStatement iopt
-> do_option
infof iopt
816 | F.SeqEnd
(i
, info
) -> infof info
817 | F.SeqStart
(st
, i
, info
) -> infof info
819 | F.MacroStmt
(st
, ((),ii
)) -> iif ii
820 | F.Asm
(st
, (asmbody
,ii
)) ->
822 vk_asmbody bigf asmbody
826 F.ErrorExit
|F.Exit
|F.Enter
|
827 F.FallThroughNode
|F.AfterNode
|F.FalseNode
|F.TrueNode
|F.InLoopNode
|
836 (* ------------------------------------------------------------------------ *)
837 and vk_info
= fun bigf info
->
838 let rec infof ii
= bigf
.kinfo
(k, bigf
) ii
843 and vk_ii
= fun bigf ii
->
844 List.iter
(vk_info bigf
) ii
847 (* ------------------------------------------------------------------------ *)
848 and vk_argument
= fun bigf arg
->
849 let rec do_action = function
850 | (ActMisc ii
) -> vk_ii bigf ii
853 | Left e
-> (vk_expr bigf
) e
854 | Right
(ArgType param
) -> vk_param bigf param
855 | Right
(ArgAction action
) -> do_action action
857 and vk_argument_list
= fun bigf es
->
858 let iif ii
= vk_ii bigf ii
in
859 es
+> List.iter
(fun (e
, ii
) ->
866 and vk_param
= fun bigf param
->
867 let iif ii
= vk_ii bigf ii
in
868 let {p_namei
= swrapopt
; p_register
= (b
, iib
); p_type
=ft
} = param
in
869 swrapopt
+> Common.do_option
(vk_name bigf
);
873 and vk_param_list
= fun bigf ts
->
874 let iif ii
= vk_ii bigf ii
in
875 ts
+> List.iter
(fun (param
,iicomma
) ->
882 (* ------------------------------------------------------------------------ *)
883 and vk_asmbody
= fun bigf
(string_list
, colon_list
) ->
884 let iif ii
= vk_ii bigf ii
in
887 colon_list
+> List.iter
(fun (Colon xs
, ii
) ->
889 xs
+> List.iter
(fun (x
,iicomma
) ->
892 | ColonMisc
, ii
-> iif ii
900 (* ------------------------------------------------------------------------ *)
901 let vk_args_splitted = fun bigf args_splitted
->
902 let iif ii
= vk_ii bigf ii
in
903 args_splitted
+> List.iter
(function
904 | Left arg
-> vk_argument bigf arg
909 let vk_define_params_splitted = fun bigf args_splitted
->
910 let iif ii
= vk_ii bigf ii
in
911 args_splitted
+> List.iter
(function
912 | Left
(s
, iis
) -> vk_ii bigf iis
918 let vk_params_splitted = fun bigf args_splitted
->
919 let iif ii
= vk_ii bigf ii
in
920 args_splitted
+> List.iter
(function
921 | Left arg
-> vk_param bigf arg
925 (* ------------------------------------------------------------------------ *)
926 let vk_cst = fun bigf
(cst
, ii
) ->
927 let iif ii
= vk_ii bigf ii
in
937 (*****************************************************************************)
938 (* "syntetisized attributes" style *)
939 (*****************************************************************************)
941 (* TODO port the xxs_s to new cpp construct too *)
943 type 'a inout
= 'a
-> 'a
945 (* _s for synthetizized attributes
947 * Note that I don't visit necesserally in the order of the token
948 * found in the original file. So don't assume such hypothesis!
951 kexpr_s
: (expression inout
* visitor_c_s
) -> expression inout
;
952 kstatement_s
: (statement inout
* visitor_c_s
) -> statement inout
;
953 ktype_s
: (fullType inout
* visitor_c_s
) -> fullType inout
;
955 kdecl_s
: (declaration inout
* visitor_c_s
) -> declaration inout
;
956 kdef_s
: (definition inout
* visitor_c_s
) -> definition inout
;
957 kname_s
: (name inout
* visitor_c_s
) -> name inout
;
959 kini_s
: (initialiser inout
* visitor_c_s
) -> initialiser inout
;
961 kcppdirective_s
: (cpp_directive inout
* visitor_c_s
) -> cpp_directive inout
;
962 kdefineval_s
: (define_val inout
* visitor_c_s
) -> define_val inout
;
963 kstatementseq_s
: (statement_sequencable inout
* visitor_c_s
) -> statement_sequencable inout
;
964 kstatementseq_list_s
: (statement_sequencable list inout
* visitor_c_s
) -> statement_sequencable list inout
;
966 knode_s
: (F.node inout
* visitor_c_s
) -> F.node inout
;
969 ktoplevel_s
: (toplevel inout
* visitor_c_s
) -> toplevel inout
;
970 kinfo_s
: (info inout
* visitor_c_s
) -> info inout
;
973 let default_visitor_c_s =
974 { kexpr_s
= (fun (k,_
) e
-> k e
);
975 kstatement_s
= (fun (k,_
) st
-> k st
);
976 ktype_s
= (fun (k,_
) t
-> k t
);
977 kdecl_s
= (fun (k,_
) d
-> k d
);
978 kdef_s
= (fun (k,_
) d
-> k d
);
979 kname_s
= (fun (k,_
) x
-> k x
);
980 kini_s
= (fun (k,_
) d
-> k d
);
981 ktoplevel_s
= (fun (k,_
) p
-> k p
);
982 knode_s
= (fun (k,_
) n
-> k n
);
983 kinfo_s
= (fun (k,_
) i
-> k i
);
984 kdefineval_s
= (fun (k,_
) x
-> k x
);
985 kstatementseq_s
= (fun (k,_
) x
-> k x
);
986 kstatementseq_list_s
= (fun (k,_
) x
-> k x
);
987 kcppdirective_s
= (fun (k,_
) x
-> k x
);
990 let rec vk_expr_s = fun bigf expr
->
991 let iif ii
= vk_ii_s bigf ii
in
992 let rec exprf e
= bigf
.kexpr_s
(k, bigf
) e
994 let ((unwrap_e
, typ
), ii
) = e
in
995 (* !!! don't analyse optional type !!!
996 * old: typ +> map_option (vk_type_s bigf) in
1001 | Ident
(name
) -> Ident
(vk_name_s bigf name
)
1002 | Constant
(c
) -> Constant
(c
)
1003 | FunCall
(e, es
) ->
1005 es
+> List.map
(fun (e,ii
) ->
1006 vk_argument_s bigf
e, iif ii
1009 | CondExpr
(e1
, e2
, e3
) -> CondExpr
(exprf e1
, fmap
exprf e2
, exprf e3
)
1010 | Sequence
(e1
, e2
) -> Sequence
(exprf e1
, exprf e2
)
1011 | Assignment
(e1
, op
, e2
) -> Assignment
(exprf e1
, op
, exprf e2
)
1013 | Postfix
(e, op
) -> Postfix
(exprf e, op
)
1014 | Infix
(e, op
) -> Infix
(exprf e, op
)
1015 | Unary
(e, op
) -> Unary
(exprf e, op
)
1016 | Binary
(e1
, op
, e2
) -> Binary
(exprf e1
, op
, exprf e2
)
1018 | ArrayAccess
(e1
, e2
) -> ArrayAccess
(exprf e1
, exprf e2
)
1019 | RecordAccess
(e, name
) ->
1020 RecordAccess
(exprf e, vk_name_s bigf name
)
1021 | RecordPtAccess
(e, name
) ->
1022 RecordPtAccess
(exprf e, vk_name_s bigf name
)
1024 | SizeOfExpr
(e) -> SizeOfExpr
(exprf e)
1025 | SizeOfType
(t
) -> SizeOfType
(vk_type_s bigf t
)
1026 | Cast
(t
, e) -> Cast
(vk_type_s bigf t
, exprf e)
1028 | StatementExpr
(statxs
, is
) ->
1030 vk_statement_sequencable_list_s bigf statxs
,
1032 | Constructor
(t
, initxs
) ->
1035 (initxs
+> List.map
(fun (ini
, ii
) ->
1036 vk_ini_s bigf ini
, vk_ii_s bigf ii
)
1039 | ParenExpr
(e) -> ParenExpr
(exprf e)
1042 (e'
, typ'
), (iif ii
)
1046 and vk_argument_s bigf argument
=
1047 let iif ii
= vk_ii_s bigf ii
in
1048 let rec do_action = function
1049 | (ActMisc ii
) -> ActMisc
(iif ii
)
1051 (match argument
with
1052 | Left
e -> Left
(vk_expr_s bigf
e)
1053 | Right
(ArgType param
) -> Right
(ArgType
(vk_param_s bigf param
))
1054 | Right
(ArgAction action
) -> Right
(ArgAction
(do_action action
))
1057 (* ------------------------------------------------------------------------ *)
1060 and vk_name_s
= fun bigf
ident ->
1061 let iif ii
= vk_ii_s bigf ii
in
1062 let rec namef x
= bigf
.kname_s
(k,bigf
) x
1065 | RegularName
(s
,ii
) -> RegularName
(s
, iif ii
)
1066 | CppConcatenatedName xs
->
1067 CppConcatenatedName
(xs
+> List.map
(fun ((x
,ii1
), ii2
) ->
1068 (x
, iif ii1
), iif ii2
1070 | CppVariadicName
(s
, ii
) -> CppVariadicName
(s
, iif ii
)
1071 | CppIdentBuilder
((s
,iis
), xs
) ->
1072 CppIdentBuilder
((s
, iif iis
),
1073 xs
+> List.map
(fun ((x
,iix
), iicomma
) ->
1074 ((x
, iif iix
), iif iicomma
)))
1079 (* ------------------------------------------------------------------------ *)
1083 and vk_statement_s
= fun bigf st
->
1084 let rec statf st
= bigf
.kstatement_s
(k, bigf
) st
1086 let (unwrap_st
, ii
) = st
in
1088 match unwrap_st
with
1089 | Labeled
(Label
(s
, st)) ->
1090 Labeled
(Label
(s
, statf st))
1091 | Labeled
(Case
(e, st)) ->
1092 Labeled
(Case
((vk_expr_s bigf
) e , statf st))
1093 | Labeled
(CaseRange
(e, e2
, st)) ->
1094 Labeled
(CaseRange
((vk_expr_s bigf
) e,
1095 (vk_expr_s bigf
) e2
,
1097 | Labeled
(Default
st) -> Labeled
(Default
(statf st))
1098 | Compound statxs
->
1099 Compound
(vk_statement_sequencable_list_s bigf statxs
)
1100 | ExprStatement
(None
) -> ExprStatement
(None
)
1101 | ExprStatement
(Some
e) -> ExprStatement
(Some
((vk_expr_s bigf
) e))
1102 | Selection
(If
(e, st1
, st2
)) ->
1103 Selection
(If
((vk_expr_s bigf
) e, statf st1
, statf st2
))
1104 | Selection
(Switch
(e, st)) ->
1105 Selection
(Switch
((vk_expr_s bigf
) e, statf st))
1106 | Iteration
(While
(e, st)) ->
1107 Iteration
(While
((vk_expr_s bigf
) e, statf st))
1108 | Iteration
(DoWhile
(st, e)) ->
1109 Iteration
(DoWhile
(statf st, (vk_expr_s bigf
) e))
1110 | Iteration
(For
((e1opt
,i1
), (e2opt
,i2
), (e3opt
,i3
), st)) ->
1111 let e1opt'
= statf (ExprStatement
(e1opt),i1
) in
1112 let e2opt'
= statf (ExprStatement
(e2opt),i2
) in
1113 let e3opt'
= statf (ExprStatement
(e3opt),i3
) in
1114 (match (e1opt'
, e2opt'
, e3opt'
) with
1115 | ((ExprStatement x1
,i1
), (ExprStatement x2
,i2
), ((ExprStatement x3
,i3
))) ->
1116 Iteration
(For
((x1
,i1
), (x2
,i2
), (x3
,i3
), statf st))
1117 | x
-> failwith
"cant be here if iterator keep ExprStatement as is"
1120 | Iteration
(MacroIteration
(s
, es
, st)) ->
1124 es
+> List.map
(fun (e, ii
) ->
1125 vk_argument_s bigf
e, vk_ii_s bigf ii
1131 | Jump
(Goto name
) -> Jump
(Goto
(vk_name_s bigf name
))
1132 | Jump
(((Continue
|Break
|Return
) as x
)) -> Jump
(x
)
1133 | Jump
(ReturnExpr
e) -> Jump
(ReturnExpr
((vk_expr_s bigf
) e))
1134 | Jump
(GotoComputed
e) -> Jump
(GotoComputed
(vk_expr_s bigf
e));
1136 | Decl decl
-> Decl
(vk_decl_s bigf decl
)
1137 | Asm asmbody
-> Asm
(vk_asmbody_s bigf asmbody
)
1138 | NestedFunc def
-> NestedFunc
(vk_def_s bigf def
)
1139 | MacroStmt
-> MacroStmt
1141 st'
, vk_ii_s bigf ii
1145 and vk_statement_sequencable_s
= fun bigf stseq
->
1146 let f = bigf
.kstatementseq_s
in
1151 StmtElem
(vk_statement_s bigf
st)
1152 | CppDirectiveStmt directive
->
1153 CppDirectiveStmt
(vk_cpp_directive_s bigf directive
)
1154 | IfdefStmt ifdef
->
1155 IfdefStmt
(vk_ifdef_directive_s bigf ifdef
)
1156 | IfdefStmt2
(ifdef
, xxs
) ->
1157 let ifdef'
= List.map
(vk_ifdef_directive_s bigf
) ifdef in
1158 let xxs'
= xxs +> List.map
(fun xs
->
1159 xs
+> vk_statement_sequencable_list_s bigf
1162 IfdefStmt2
(ifdef'
, xxs'
)
1163 in f (k, bigf
) stseq
1165 and vk_statement_sequencable_list_s
= fun bigf statxs
->
1166 let f = bigf
.kstatementseq_list_s
in
1168 xs
+> List.map
(vk_statement_sequencable_s bigf
)
1174 and vk_asmbody_s
= fun bigf
(string_list
, colon_list
) ->
1175 let iif ii
= vk_ii_s bigf ii
in
1178 colon_list
+> List.map
(fun (Colon xs
, ii
) ->
1180 (xs
+> List.map
(fun (x
, iicomma
) ->
1182 | ColonMisc
, ii
-> ColonMisc
, iif ii
1183 | ColonExpr
e, ii
-> ColonExpr
(vk_expr_s bigf
e), iif ii
1192 (* todo? a visitor for qualifier *)
1193 and vk_type_s
= fun bigf t
->
1194 let rec typef t
= bigf
.ktype_s
(k,bigf
) t
1195 and iif ii
= vk_ii_s bigf ii
1198 let (unwrap_q
, iiq
) = q
in
1199 (* strip_info_visitor needs iiq to be processed before iit *)
1200 let iif_iiq = iif iiq
in
1201 let q'
= unwrap_q
in
1202 let (unwrap_t
, iit
) = t
in
1205 | BaseType x
-> BaseType x
1206 | Pointer
t -> Pointer
(typef t)
1207 | Array
(eopt
, t) -> Array
(fmap
(vk_expr_s bigf
) eopt
, typef t)
1208 | FunctionType
(returnt
, paramst
) ->
1212 | (ts
, (b
, iihas3dots
)) ->
1213 (ts
+> List.map
(fun (param
,iicomma
) ->
1214 (vk_param_s bigf param
, iif iicomma
)),
1215 (b
, iif iihas3dots
))
1218 | Enum
(sopt
, enumt
) ->
1220 enumt
+> List.map
(fun ((name
, eopt
), iicomma
) ->
1222 ((vk_name_s bigf name
,
1223 eopt
+> Common.fmap
(fun (info
, e) ->
1224 vk_info_s bigf info
,
1230 | StructUnion
(sopt
, su
, fields
) ->
1231 StructUnion
(sopt
, su
, vk_struct_fields_s bigf fields
)
1234 | StructUnionName
(s
, structunion
) -> StructUnionName
(s
, structunion
)
1235 | EnumName s
-> EnumName s
1236 | TypeName
(name
, typ) -> TypeName
(vk_name_s bigf name
, typ)
1238 | ParenType
t -> ParenType
(typef t)
1239 | TypeOfExpr
e -> TypeOfExpr
(vk_expr_s bigf
e)
1240 | TypeOfType
t -> TypeOfType
(typef t)
1248 and vk_attribute_s
= fun bigf attr
->
1249 let iif ii
= vk_ii_s bigf ii
in
1251 | Attribute s
, ii
->
1256 and vk_decl_s
= fun bigf d
->
1257 let f = bigf
.kdecl_s
in
1258 let iif ii
= vk_ii_s bigf ii
in
1261 | DeclList
(xs
, ii
) ->
1262 DeclList
(List.map aux xs
, iif ii
)
1263 | MacroDecl
((s
, args
),ii
) ->
1266 args
+> List.map
(fun (e,ii
) -> vk_argument_s bigf
e, iif ii
)
1271 and aux
({v_namei
= var
;
1275 v_attr
= attrs
}, iicomma
) =
1277 (var
+> map_option
(fun (name
, iniopt
) ->
1278 vk_name_s bigf name
,
1279 iniopt
+> map_option
(fun (info
, init
) ->
1280 vk_info_s bigf info
,
1283 v_type
= vk_type_s bigf
t;
1286 v_attr
= attrs
+> List.map
(vk_attribute_s bigf
);
1292 and vk_ini_s
= fun bigf ini
->
1293 let rec inif ini
= bigf
.kini_s
(k,bigf
) ini
1295 let (unwrap_ini
, ii
) = ini
in
1297 match unwrap_ini
with
1298 | InitExpr
e -> InitExpr
(vk_expr_s bigf
e)
1299 | InitList initxs
->
1300 InitList
(initxs
+> List.map
(fun (ini, ii
) ->
1301 inif ini, vk_ii_s bigf ii
)
1305 | InitDesignators
(xs
, e) ->
1307 (xs
+> List.map
(vk_designator_s bigf
),
1311 | InitFieldOld
(s
, e) -> InitFieldOld
(s
, inif e)
1312 | InitIndexOld
(e1
, e) -> InitIndexOld
(vk_expr_s bigf e1
, inif e)
1315 in ini'
, vk_ii_s bigf ii
1319 and vk_designator_s
= fun bigf design
->
1320 let iif ii
= vk_ii_s bigf ii
in
1321 let (designator
, ii
) = design
in
1322 (match designator
with
1323 | DesignatorField s
-> DesignatorField s
1324 | DesignatorIndex
e -> DesignatorIndex
(vk_expr_s bigf
e)
1325 | DesignatorRange
(e1
, e2
) ->
1326 DesignatorRange
(vk_expr_s bigf e1
, vk_expr_s bigf e2
)
1332 and vk_struct_fieldkinds_s
= fun bigf onefield_multivars
->
1333 let iif ii
= vk_ii_s bigf ii
in
1335 onefield_multivars
+> List.map
(fun (field
, iicomma
) ->
1337 | Simple
(nameopt
, t) ->
1338 Simple
(Common.map_option
(vk_name_s bigf
) nameopt
,
1340 | BitField
(nameopt
, t, info
, expr
) ->
1341 BitField
(Common.map_option
(vk_name_s bigf
) nameopt
,
1343 vk_info_s bigf info
,
1344 vk_expr_s bigf expr
)
1348 and vk_struct_fields_s
= fun bigf fields
->
1350 let iif ii
= vk_ii_s bigf ii
in
1352 fields
+> List.map
(fun (xfield
, iiptvirg
) ->
1355 | (DeclarationField
(FieldDeclList
(onefield_multivars
, iiptvirg
))) ->
1358 (vk_struct_fieldkinds_s bigf onefield_multivars
, iif iiptvirg
))
1359 | EmptyField
-> EmptyField
1360 | MacroStructDeclTodo
->
1361 pr2_once
"MacroStructDeclTodo";
1364 | CppDirectiveStruct directive
->
1365 CppDirectiveStruct
(vk_cpp_directive_s bigf directive
)
1366 | IfdefStruct
ifdef ->
1367 IfdefStruct
(vk_ifdef_directive_s bigf
ifdef)
1373 and vk_def_s
= fun bigf d
->
1374 let f = bigf
.kdef_s
in
1375 let iif ii
= vk_ii_s bigf ii
in
1379 f_type
= (returnt
, (paramst
, (b
, iib
)));
1383 f_old_c_style
= oldstyle
;
1388 (vk_type_s bigf returnt
,
1389 (paramst
+> List.map
(fun (param
, iicomma
) ->
1390 (vk_param_s bigf param
, iif iicomma
)
1394 vk_statement_sequencable_list_s bigf statxs
;
1396 attrs
+> List.map
(vk_attribute_s bigf
);
1398 oldstyle
+> Common.map_option
(fun decls
->
1399 decls
+> List.map
(vk_decl_s bigf
)
1406 and vk_toplevel_s
= fun bigf p
->
1407 let f = bigf
.ktoplevel_s
in
1408 let iif ii
= vk_ii_s bigf ii
in
1411 | Declaration decl
-> Declaration
(vk_decl_s bigf decl
)
1412 | Definition def
-> Definition
(vk_def_s bigf def
)
1413 | EmptyDef ii
-> EmptyDef
(iif ii
)
1414 | MacroTop
(s
, xs
, ii
) ->
1417 xs
+> List.map
(fun (elem
, iicomma
) ->
1418 vk_argument_s bigf elem
, iif iicomma
1422 | CppTop top
-> CppTop
(vk_cpp_directive_s bigf top
)
1423 | IfdefTop ifdefdir
-> IfdefTop
(vk_ifdef_directive_s bigf ifdefdir
)
1425 | NotParsedCorrectly ii
-> NotParsedCorrectly
(iif ii
)
1426 | FinalDef info
-> FinalDef
(vk_info_s bigf info
)
1429 and vk_program_s
= fun bigf xs
->
1430 xs
+> List.map
(vk_toplevel_s bigf
)
1433 and vk_cpp_directive_s
= fun bigf top
->
1434 let iif ii
= vk_ii_s bigf ii
in
1435 let f = bigf
.kcppdirective_s
in
1439 | Include
{i_include
= (s
, ii
);
1440 i_rel_pos
= h_rel_pos
;
1444 -> Include
{i_include
= (s
, iif ii
);
1445 i_rel_pos
= h_rel_pos
;
1447 i_content
= copt
+> Common.map_option
(fun (file
, asts
) ->
1448 file
, vk_program_s bigf asts
1451 | Define
((s
,ii
), (defkind
, defval
)) ->
1452 Define
((s
, iif ii
),
1453 (vk_define_kind_s bigf defkind
, vk_define_val_s bigf defval
))
1454 | Undef
(s
, ii
) -> Undef
(s
, iif ii
)
1455 | PragmaAndCo
(ii
) -> PragmaAndCo
(iif ii
)
1459 and vk_ifdef_directive_s
= fun bigf
ifdef ->
1460 let iif ii
= vk_ii_s bigf ii
in
1462 | IfdefDirective
(ifkind
, ii
) -> IfdefDirective
(ifkind
, iif ii
)
1466 and vk_define_kind_s
= fun bigf defkind
->
1468 | DefineVar
-> DefineVar
1469 | DefineFunc
(params
, ii
) ->
1471 (params
+> List.map
(fun ((s
,iis
),iicomma
) ->
1472 ((s
, vk_ii_s bigf iis
), vk_ii_s bigf iicomma
)
1478 and vk_define_val_s
= fun bigf x
->
1479 let f = bigf
.kdefineval_s
in
1480 let iif ii
= vk_ii_s bigf ii
in
1483 | DefineExpr
e -> DefineExpr
(vk_expr_s bigf
e)
1484 | DefineStmt
st -> DefineStmt
(vk_statement_s bigf
st)
1485 | DefineDoWhileZero
((st,e),ii
) ->
1486 let st'
= vk_statement_s bigf
st in
1487 let e'
= vk_expr_s bigf
e in
1488 DefineDoWhileZero
((st'
,e'
), iif ii
)
1489 | DefineFunction def
-> DefineFunction
(vk_def_s bigf def
)
1490 | DefineType ty
-> DefineType
(vk_type_s bigf ty
)
1491 | DefineText
(s
, ii
) -> DefineText
(s
, iif ii
)
1492 | DefineEmpty
-> DefineEmpty
1493 | DefineInit
ini -> DefineInit
(vk_ini_s bigf
ini)
1496 pr2_once
"DefineTodo";
1502 and vk_info_s
= fun bigf info
->
1503 let rec infof ii
= bigf
.kinfo_s
(k, bigf
) ii
1508 and vk_ii_s
= fun bigf ii
->
1509 List.map
(vk_info_s bigf
) ii
1511 (* ------------------------------------------------------------------------ *)
1512 and vk_node_s
= fun bigf node
->
1513 let iif ii
= vk_ii_s bigf ii
in
1514 let infof info
= vk_info_s bigf info
in
1516 let rec nodef n
= bigf
.knode_s
(k, bigf
) n
1519 match F.unwrap node
with
1520 | F.FunHeader
(def
) ->
1521 assert (null
(fst def
).f_body
);
1522 F.FunHeader
(vk_def_s bigf def
)
1524 | F.Decl declb
-> F.Decl
(vk_decl_s bigf declb
)
1525 | F.ExprStatement
(st, (eopt
, ii
)) ->
1526 F.ExprStatement
(st, (eopt
+> map_option
(vk_expr_s bigf
), iif ii
))
1528 | F.IfHeader
(st, (e,ii
)) ->
1529 F.IfHeader
(st, (vk_expr_s bigf
e, iif ii
))
1530 | F.SwitchHeader
(st, (e,ii
)) ->
1531 F.SwitchHeader
(st, (vk_expr_s bigf
e, iif ii
))
1532 | F.WhileHeader
(st, (e,ii
)) ->
1533 F.WhileHeader
(st, (vk_expr_s bigf
e, iif ii
))
1534 | F.DoWhileTail
(e,ii
) ->
1535 F.DoWhileTail
(vk_expr_s bigf
e, iif ii
)
1537 | F.ForHeader
(st, (((e1opt,i1
), (e2opt,i2
), (e3opt,i3
)), ii
)) ->
1539 (((e1opt +> Common.map_option
(vk_expr_s bigf
), iif i1
),
1540 (e2opt +> Common.map_option
(vk_expr_s bigf
), iif i2
),
1541 (e3opt +> Common.map_option
(vk_expr_s bigf
), iif i3
)),
1544 | F.MacroIterHeader
(st, ((s
,es
), ii
)) ->
1547 ((s
, es
+> List.map
(fun (e, ii
) -> vk_argument_s bigf
e, iif ii
)),
1551 | F.ReturnExpr
(st, (e,ii
)) ->
1552 F.ReturnExpr
(st, (vk_expr_s bigf
e, iif ii
))
1554 | F.Case
(st, (e,ii
)) -> F.Case
(st, (vk_expr_s bigf
e, iif ii
))
1555 | F.CaseRange
(st, ((e1
, e2
),ii
)) ->
1556 F.CaseRange
(st, ((vk_expr_s bigf e1
, vk_expr_s bigf e2
), iif ii
))
1558 | F.CaseNode i
-> F.CaseNode i
1560 | F.DefineHeader
((s
,ii
), (defkind
)) ->
1561 F.DefineHeader
((s
, iif ii
), (vk_define_kind_s bigf defkind
))
1563 | F.DefineExpr
e -> F.DefineExpr
(vk_expr_s bigf
e)
1564 | F.DefineType ft
-> F.DefineType
(vk_type_s bigf ft
)
1565 | F.DefineDoWhileZeroHeader
((),ii
) ->
1566 F.DefineDoWhileZeroHeader
((),iif ii
)
1567 | F.DefineTodo
-> F.DefineTodo
1569 | F.Include
{i_include
= (s
, ii
);
1570 i_rel_pos
= h_rel_pos
;
1575 assert (copt
=*= None
);
1576 F.Include
{i_include
= (s
, iif ii
);
1577 i_rel_pos
= h_rel_pos
;
1582 | F.MacroTop
(s
, args
, ii
) ->
1585 args
+> List.map
(fun (e, ii
) -> vk_argument_s bigf
e, iif ii
),
1589 | F.MacroStmt
(st, ((),ii
)) -> F.MacroStmt
(st, ((),iif ii
))
1590 | F.Asm
(st, (body
,ii
)) -> F.Asm
(st, (vk_asmbody_s bigf body
,iif ii
))
1592 | F.Break
(st,((),ii
)) -> F.Break
(st,((),iif ii
))
1593 | F.Continue
(st,((),ii
)) -> F.Continue
(st,((),iif ii
))
1594 | F.Default
(st,((),ii
)) -> F.Default
(st,((),iif ii
))
1595 | F.Return
(st,((),ii
)) -> F.Return
(st,((),iif ii
))
1596 | F.Goto
(st, name
, ((),ii
)) ->
1597 F.Goto
(st, vk_name_s bigf name
, ((),iif ii
))
1598 | F.Label
(st, name
, ((),ii
)) ->
1599 F.Label
(st, vk_name_s bigf name
, ((),iif ii
))
1600 | F.EndStatement iopt
-> F.EndStatement
(map_option
infof iopt
)
1601 | F.DoHeader
(st, info
) -> F.DoHeader
(st, infof info
)
1602 | F.Else info
-> F.Else
(infof info
)
1603 | F.SeqEnd
(i
, info
) -> F.SeqEnd
(i
, infof info
)
1604 | F.SeqStart
(st, i
, info
) -> F.SeqStart
(st, i
, infof info
)
1606 | F.IfdefHeader
(info
) -> F.IfdefHeader
(vk_ifdef_directive_s bigf info
)
1607 | F.IfdefElse
(info
) -> F.IfdefElse
(vk_ifdef_directive_s bigf info
)
1608 | F.IfdefEndif
(info
) -> F.IfdefEndif
(vk_ifdef_directive_s bigf info
)
1612 F.TopNode
|F.EndNode
|
1613 F.ErrorExit
|F.Exit
|F.Enter
|
1614 F.FallThroughNode
|F.AfterNode
|F.FalseNode
|F.TrueNode
|F.InLoopNode
|
1623 (* ------------------------------------------------------------------------ *)
1624 and vk_param_s
= fun bigf param
->
1625 let iif ii
= vk_ii_s bigf ii
in
1626 let {p_namei
= swrapopt
; p_register
= (b
, iib
); p_type
=ft
} = param
in
1627 { p_namei
= swrapopt
+> Common.map_option
(vk_name_s bigf
);
1628 p_register
= (b
, iif iib
);
1629 p_type
= vk_type_s bigf ft
;
1632 let vk_args_splitted_s = fun bigf args_splitted
->
1633 let iif ii
= vk_ii_s bigf ii
in
1634 args_splitted
+> List.map
(function
1635 | Left arg
-> Left
(vk_argument_s bigf arg
)
1636 | Right ii
-> Right
(iif ii
)
1639 let vk_arguments_s = fun bigf args
->
1640 let iif ii
= vk_ii_s bigf ii
in
1641 args
+> List.map
(fun (e, ii
) -> vk_argument_s bigf
e, iif ii
)
1644 let vk_params_splitted_s = fun bigf args_splitted
->
1645 let iif ii
= vk_ii_s bigf ii
in
1646 args_splitted
+> List.map
(function
1647 | Left arg
-> Left
(vk_param_s bigf arg
)
1648 | Right ii
-> Right
(iif ii
)
1651 let vk_params_s = fun bigf args
->
1652 let iif ii
= vk_ii_s bigf ii
in
1653 args
+> List.map
(fun (p
,ii
) -> vk_param_s bigf p
, iif ii
)
1655 let vk_define_params_splitted_s = fun bigf args_splitted
->
1656 let iif ii
= vk_ii_s bigf ii
in
1657 args_splitted
+> List.map
(function
1658 | Left
(s
, iis
) -> Left
(s
, vk_ii_s bigf iis
)
1659 | Right ii
-> Right
(iif ii
)
1662 let vk_cst_s = fun bigf
(cst
, ii
) ->
1663 let iif ii
= vk_ii_s bigf ii
in
1665 | Left cst
-> Left cst
1666 | Right s
-> Right s