--- /dev/null
+.depend
+Makefile.config
+spatch
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Coccinelle</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>Ocaml.ocamlMakefileBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>ocaml.ocamlnatureMakefile</nature>
+ </natures>
+</projectDescription>
MAKESUBDIRS=commons globals menhirlib $(PYDIR) ctl parsing_cocci parsing_c \
engine popl09 extra python
-INCLUDEDIRS=commons globals menhirlib $(PYDIR) ctl parsing_cocci parsing_c \
- engine popl09 extra python
+INCLUDEDIRS=commons commons/ocamlextra globals menhirlib $(PYDIR) ctl \
+ parsing_cocci parsing_c engine popl09 extra python
##############################################################################
# Generic variables
##############################################################################
# Top rules
##############################################################################
+eclipse: depend all
+configure:
+ ./configure
all: rec $(EXEC)
opt: rec.opt $(EXEC).opt
rm -f dllpycaml_stubs.so
-.PHONY: tools
+.PHONY: tools all configure
tools:
$(MAKE) -C tools
bintar: all
rm -f $(TMP)/$(PACKAGE)
ln -s `pwd` $(TMP)/$(PACKAGE)
- cd $(TMP); tar cvfz $(PACKAGE)-bin-x86.tgz $(BINSRC2)
+ cd $(TMP); tar cvfz $(PACKAGE)-bin-x86.tgz --exclude=CVS $(BINSRC2)
rm -f $(TMP)/$(PACKAGE)
staticbintar: all.opt
rm -f $(TMP)/$(PACKAGE)
ln -s `pwd` $(TMP)/$(PACKAGE)
make static
- cd $(TMP); tar cvfz $(PACKAGE)-bin-x86-static.tgz $(BINSRC2)
+ cd $(TMP); tar cvfz $(PACKAGE)-bin-x86-static.tgz --exclude=CVS $(BINSRC2)
rm -f $(TMP)/$(PACKAGE)
# add ocaml version in name ?
rm -f $(TMP)/$(PACKAGE)
ln -s `pwd` $(TMP)/$(PACKAGE)
make purebytecode
- cd $(TMP); tar cvfz $(PACKAGE)-bin-bytecode-$(OCAMLVERSION).tgz $(BINSRC2)
+ cd $(TMP); tar cvfz $(PACKAGE)-bin-bytecode-$(OCAMLVERSION).tgz --exclude=CVS $(BINSRC2)
rm -f $(TMP)/$(PACKAGE)
clean::
-*- org -*-
+* 0.1.1
+
+** better support for initializer, cf -test substruct
+
* 0.1
** first public release of the source code:
(interpret_dependencies local global s2)
| Ast_cocci.NoDep -> true
-let rec print_dependencies local global =
- let seen = ref [] in
- let rec loop = function
- Ast_cocci.Dep s | Ast_cocci.AntiDep s ->
- if not (List.mem s !seen)
- then
- begin
- if List.mem s local
- then pr2 (s^" satisfied")
- else pr2 (s^" not satisfied");
- seen := s :: !seen
- end
- | Ast_cocci.EverDep s | Ast_cocci.NeverDep s ->
- if not (List.mem s !seen)
- then
- begin
- if List.mem s global
- then pr2 (s^" satisfied")
- else pr2 (s^" not satisfied");
- seen := s :: !seen
- end
- | Ast_cocci.AndDep(s1,s2) ->
- print_dependencies local global s1;
- print_dependencies local global s2
- | Ast_cocci.OrDep(s1,s2) ->
- print_dependencies local global s1;
- print_dependencies local global s2
- | Ast_cocci.NoDep -> () in
- loop
-
+let rec print_dependencies str local global dep =
+ if !Flag_cocci.show_dependencies
+ then
+ begin
+ pr2 str;
+ let seen = ref [] in
+ let rec loop = function
+ Ast_cocci.Dep s | Ast_cocci.AntiDep s ->
+ if not (List.mem s !seen)
+ then
+ begin
+ if List.mem s local
+ then pr2 (s^" satisfied")
+ else pr2 (s^" not satisfied");
+ seen := s :: !seen
+ end
+ | Ast_cocci.EverDep s | Ast_cocci.NeverDep s ->
+ if not (List.mem s !seen)
+ then
+ begin
+ if List.mem s global
+ then pr2 (s^" satisfied")
+ else pr2 (s^" not satisfied");
+ seen := s :: !seen
+ end
+ | Ast_cocci.AndDep(s1,s2) ->
+ loop s1;
+ loop s2
+ | Ast_cocci.OrDep(s1,s2) ->
+ loop s1;
+ loop s2
+ | Ast_cocci.NoDep -> () in
+ loop dep
+ end
!rules_that_have_ever_matched r.scr_dependencies)
then
begin
- if !Flag.show_misc
- then
- begin
- pr2 ("dependencies for script not satisfied:");
- print_dependencies rules_that_have_matched
- !rules_that_have_ever_matched r.scr_dependencies;
- show_or_not_binding "in environment" e
- end;
+ print_dependencies "dependencies for script not satisfied:"
+ rules_that_have_matched
+ !rules_that_have_ever_matched r.scr_dependencies;
+ show_or_not_binding "in environment" e;
(cache, (e, rules_that_have_matched)::newes)
end
else
begin
let (_, mv, _) = r.scr_ast_rule in
- show_or_not_binding "in" e;
if List.for_all (Pycocci.contains_binding e) mv
then
begin
then cache
else
begin
+ print_dependencies "dependencies for script satisfied:"
+ rules_that_have_matched
+ !rules_that_have_ever_matched r.scr_dependencies;
+ show_or_not_binding "in" e;
Pycocci.build_classes (List.map (function (x,y) -> x) e);
Pycocci.construct_variables mv e;
let _ = Pycocci.pyrun_simplestring
relevant_bindings :: cache
end in
if !Pycocci.inc_match
- then (new_cache, (e, rules_that_have_matched)::newes)
+ then (new_cache, merge_env [(e, rules_that_have_matched)] newes)
else (new_cache, newes)
end
- else (cache, (e, rules_that_have_matched)::newes)
+ else (cache, merge_env [(e, rules_that_have_matched)] newes)
end
and apply_cocci_rule r rules_that_have_ever_matched es ccs =
!rules_that_have_ever_matched r.dependencies)
then
begin
- if !Flag.show_misc
- then
- begin
- pr2
- ("dependencies for rule "^r.rulename^" not satisfied:");
- print_dependencies rules_that_have_matched
- !rules_that_have_ever_matched r.dependencies;
- show_or_not_binding "in environment" e
- end;
+ print_dependencies
+ ("dependencies for rule "^r.rulename^" not satisfied:")
+ rules_that_have_matched
+ !rules_that_have_ever_matched r.dependencies;
+ show_or_not_binding "in environment" e;
(cache,
- Common.union_set newes
+ merge_env
[(e +> List.filter (fun (s,v) -> List.mem s r.used_after),
- rules_that_have_matched)])
+ rules_that_have_matched)]
+ newes)
end
else
let new_bindings =
try List.assoc relevant_bindings cache
with
Not_found ->
- begin
- show_or_not_binding "in" e;
- show_or_not_binding "relevant in" relevant_bindings;
+ print_dependencies
+ ("dependencies for rule "^r.rulename^" satisfied:")
+ rules_that_have_matched
+ !rules_that_have_ever_matched r.dependencies;
+ show_or_not_binding "in" e;
+ show_or_not_binding "relevant in" relevant_bindings;
- let children_e = ref [] in
+ let children_e = ref [] in
(* looping over the functions and toplevel elements in
.c and .h *)
- concat_headers_and_c !ccs +> List.iter (fun c ->
- if c.flow <> None
- then
+ concat_headers_and_c !ccs +> List.iter (fun c ->
+ if c.flow <> None
+ then
(* does also some side effects on c and r *)
- let processed =
- process_a_ctl_a_env_a_toplevel r relevant_bindings
- c in
- match processed with
- | None -> ()
- | Some newbindings ->
- newbindings +> List.iter (fun newbinding ->
- children_e :=
- Common.insert_set newbinding !children_e)
- ); (* end iter cs *)
-
- !children_e
- end in
+ let processed =
+ process_a_ctl_a_env_a_toplevel r relevant_bindings
+ c in
+ match processed with
+ | None -> ()
+ | Some newbindings ->
+ newbindings +> List.iter (fun newbinding ->
+ children_e :=
+ Common.insert_set newbinding !children_e)
+ ); (* end iter cs *)
+
+ !children_e in
let old_bindings_to_keep =
Common.nub
(e +> List.filter (fun (s,v) -> List.mem s r.used_after)) in
not (List.mem s old_variables)))) in
List.map
(function new_binding_to_add ->
- (Common.union_set
- old_bindings_to_keep new_binding_to_add,
+ (List.sort compare
+ (Common.union_set
+ old_bindings_to_keep new_binding_to_add),
r.rulename::rules_that_have_matched))
new_bindings_to_add in
((relevant_bindings,new_bindings)::cache,
- Common.union_set new_e newes))
+ merge_env new_e newes))
([],[]) reorganized_env in (* end iter es *)
if !(r.was_matched)
then Common.push2 r.rulename rules_that_have_ever_matched;
then ccs := rebuild_info_c_and_headers !ccs r.isexp
)
+and merge_env new_e old_e =
+ List.fold_left
+ (function old_e ->
+ function (e,rules) as elem ->
+ let (same,diff) = List.partition (function (e1,_) -> e = e1) old_e in
+ match same with
+ [] -> elem :: old_e
+ | [(_,old_rules)] -> (e,Common.union_set rules old_rules) :: diff
+ | _ -> failwith "duplicate environment entries")
+ old_e new_e
+
and bigloop2 rs ccs =
let es = ref [(Ast_c.emptyMetavarsBinding,[])] in
let ccs = ref ccs in
and process_a_ctl_a_env_a_toplevel2 r e c =
indent_do (fun () ->
show_or_not_celem "trying" c.ast_c;
- let (trans_info, returned_any_states, newbindings) =
+ let (trans_info, returned_any_states, inherited_bindings, newbindings) =
Common.save_excursion Flag_ctl.loop_in_src_code (fun () ->
Flag_ctl.loop_in_src_code := !Flag_ctl.loop_in_src_code||c.contain_loop;
(* modify ast via side effect *)
ignore(Transformation3.transform r.rulename r.dropped_isos
- trans_info (Common.some c.flow));
+ inherited_bindings trans_info (Common.some c.flow));
with Timeout -> raise Timeout | UnixExit i -> raise (UnixExit i)
end;
- Some newbindings
+ Some (List.map (function x -> x@inherited_bindings) newbindings)
end
)
-Release coccinelle-0.1
+Release coccinelle-0.1.1
- * First public release of the source code:
- * Features
- - embeded python scripting
- - position
+** Language:
+ - support for initializer at toplevel, cf -test substruct
--- /dev/null
+.depend
+*.cma
--- /dev/null
+.depend
+*.cma
;;; Usage
+;; Copy this file in your ~/.emacs.d directory
+;;
;; Add the following lines to your ~/.emacs or equivalent:
+;; (load "~/.emacs.d/cocci.el")
;; (setq auto-mode-alist
;; (cons '("\\.cocci$" . cocci-mode) auto-mode-alist))
;; (autoload 'cocci-mode "cocci"
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* for MINUS and CONTEXT, pos is always None in this file *)
+(*search for require*)
+(* true = don't see all matched nodes, only modified ones *)
+let onlyModif = ref true(*false*)
+
+type ex = Exists | Forall | ReverseForall
+let exists = ref Forall
+
+module Ast = Ast_cocci
+module V = Visitor_ast
+module CTL = Ast_ctl
+
+let warning s = Printf.fprintf stderr "warning: %s\n" s
+
+type cocci_predicate = Lib_engine.predicate * Ast.meta_name Ast_ctl.modif
+type formula =
+ (cocci_predicate,Ast.meta_name, Wrapper_ctl.info) Ast_ctl.generic_ctl
+
+let union = Common.union_set
+let intersect l1 l2 = List.filter (function x -> List.mem x l2) l1
+let subset l1 l2 = List.for_all (function x -> List.mem x l2) l1
+
+let foldl1 f xs = List.fold_left f (List.hd xs) (List.tl xs)
+let foldr1 f xs =
+ let xs = List.rev xs in List.fold_left f (List.hd xs) (List.tl xs)
+
+let used_after = ref ([] : Ast.meta_name list)
+let guard_to_strict guard = if guard then CTL.NONSTRICT else CTL.STRICT
+
+let saved = ref ([] : Ast.meta_name list)
+
+let string2var x = ("",x)
+
+(* --------------------------------------------------------------------- *)
+(* predicates matching various nodes in the graph *)
+
+let ctl_and s x y =
+ match (x,y) with
+ (CTL.False,_) | (_,CTL.False) -> CTL.False
+ | (CTL.True,a) | (a,CTL.True) -> a
+ | _ -> CTL.And(s,x,y)
+
+let ctl_or x y =
+ match (x,y) with
+ (CTL.True,_) | (_,CTL.True) -> CTL.True
+ | (CTL.False,a) | (a,CTL.False) -> a
+ | _ -> CTL.Or(x,y)
+
+let ctl_or_fl x y =
+ match (x,y) with
+ (CTL.True,_) | (_,CTL.True) -> CTL.True
+ | (CTL.False,a) | (a,CTL.False) -> a
+ | _ -> CTL.Or(y,x)
+
+let ctl_seqor x y =
+ match (x,y) with
+ (CTL.True,_) | (_,CTL.True) -> CTL.True
+ | (CTL.False,a) | (a,CTL.False) -> a
+ | _ -> CTL.SeqOr(x,y)
+
+let ctl_not = function
+ CTL.True -> CTL.False
+ | CTL.False -> CTL.True
+ | x -> CTL.Not(x)
+
+let ctl_ax s = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x ->
+ match !exists with
+ Exists -> CTL.EX(CTL.FORWARD,x)
+ | Forall -> CTL.AX(CTL.FORWARD,s,x)
+ | ReverseForall -> failwith "not supported"
+
+let ctl_ax_absolute s = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.AX(CTL.FORWARD,s,x)
+
+let ctl_ex = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.EX(CTL.FORWARD,x)
+
+(* This stays being AX even for sgrep_mode, because it is used to identify
+the structure of the term, not matching the pattern. *)
+let ctl_back_ax = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.AX(CTL.BACKWARD,CTL.NONSTRICT,x)
+
+let ctl_back_ex = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.EX(CTL.BACKWARD,x)
+
+let ctl_ef = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.EF(CTL.FORWARD,x)
+
+let ctl_ag s = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.AG(CTL.FORWARD,s,x)
+
+let ctl_au s x y =
+ match (x,!exists) with
+ (CTL.True,Exists) -> CTL.EF(CTL.FORWARD,y)
+ | (CTL.True,Forall) -> CTL.AF(CTL.FORWARD,s,y)
+ | (CTL.True,ReverseForall) -> failwith "not supported"
+ | (_,Exists) -> CTL.EU(CTL.FORWARD,x,y)
+ | (_,Forall) -> CTL.AU(CTL.FORWARD,s,x,y)
+ | (_,ReverseForall) -> failwith "not supported"
+
+let ctl_anti_au s x y = (* only for ..., where the quantifier is changed *)
+ CTL.XX
+ (match (x,!exists) with
+ (CTL.True,Exists) -> CTL.AF(CTL.FORWARD,s,y)
+ | (CTL.True,Forall) -> CTL.EF(CTL.FORWARD,y)
+ | (CTL.True,ReverseForall) -> failwith "not supported"
+ | (_,Exists) -> CTL.AU(CTL.FORWARD,s,x,y)
+ | (_,Forall) -> CTL.EU(CTL.FORWARD,x,y)
+ | (_,ReverseForall) -> failwith "not supported")
+
+let ctl_uncheck = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.Uncheck x
+
+let label_pred_maker = function
+ None -> CTL.True
+ | Some (label_var,used) ->
+ used := true;
+ CTL.Pred(Lib_engine.PrefixLabel(label_var),CTL.Control)
+
+let bclabel_pred_maker = function
+ None -> CTL.True
+ | Some (label_var,used) ->
+ used := true;
+ CTL.Pred(Lib_engine.BCLabel(label_var),CTL.Control)
+
+let predmaker guard pred label =
+ ctl_and (guard_to_strict guard) (CTL.Pred pred) (label_pred_maker label)
+
+let aftpred = predmaker false (Lib_engine.After, CTL.Control)
+let retpred = predmaker false (Lib_engine.Return, CTL.Control)
+let funpred = predmaker false (Lib_engine.FunHeader, CTL.Control)
+let toppred = predmaker false (Lib_engine.Top, CTL.Control)
+let exitpred = predmaker false (Lib_engine.ErrorExit, CTL.Control)
+let endpred = predmaker false (Lib_engine.Exit, CTL.Control)
+let gotopred = predmaker false (Lib_engine.Goto, CTL.Control)
+let inlooppred = predmaker false (Lib_engine.InLoop, CTL.Control)
+let truepred = predmaker false (Lib_engine.TrueBranch, CTL.Control)
+let falsepred = predmaker false (Lib_engine.FalseBranch, CTL.Control)
+let fallpred = predmaker false (Lib_engine.FallThrough, CTL.Control)
+
+let aftret label_var f = ctl_or (aftpred label_var) (exitpred label_var)
+
+let letctr = ref 0
+let get_let_ctr _ =
+ let cur = !letctr in
+ letctr := cur + 1;
+ Printf.sprintf "r%d" cur
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Eliminate OptStm *)
+
+(* for optional thing with nothing after, should check that the optional thing
+never occurs. otherwise the matching stops before it occurs *)
+let elim_opt =
+ let mcode x = x in
+ let donothing r k e = k e in
+
+ let fvlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_fvs l) in
+
+ let mfvlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_mfvs l) in
+
+ let freshlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_fresh l) in
+
+ let inheritedlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_inherited l) in
+
+ let savedlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_saved l) in
+
+ let varlists l =
+ (fvlist l, mfvlist l, freshlist l, inheritedlist l, savedlist l) in
+
+ let rec dots_list unwrapped wrapped =
+ match (unwrapped,wrapped) with
+ ([],_) -> []
+
+ | (Ast.Dots(_,_,_,_)::Ast.OptStm(stm)::(Ast.Dots(_,_,_,_) as u)::urest,
+ d0::s::d1::rest)
+ | (Ast.Nest(_,_,_,_,_)::Ast.OptStm(stm)::(Ast.Dots(_,_,_,_) as u)::urest,
+ d0::s::d1::rest) ->
+ let l = Ast.get_line stm in
+ let new_rest1 = stm :: (dots_list (u::urest) (d1::rest)) in
+ let new_rest2 = dots_list urest rest in
+ let (fv_rest1,mfv_rest1,fresh_rest1,inherited_rest1,s1) =
+ varlists new_rest1 in
+ let (fv_rest2,mfv_rest2,fresh_rest2,inherited_rest2,s2) =
+ varlists new_rest2 in
+ [d0;
+ {(Ast.make_term
+ (Ast.Disj
+ [{(Ast.make_term(Ast.DOTS(new_rest1))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest1;
+ Ast.minus_free_vars = mfv_rest1;
+ Ast.fresh_vars = fresh_rest1;
+ Ast.inherited = inherited_rest1;
+ Ast.saved_witness = s1};
+ {(Ast.make_term(Ast.DOTS(new_rest2))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest2;
+ Ast.minus_free_vars = mfv_rest2;
+ Ast.fresh_vars = fresh_rest2;
+ Ast.inherited = inherited_rest2;
+ Ast.saved_witness = s2}])) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest1;
+ Ast.minus_free_vars = mfv_rest1;
+ Ast.fresh_vars = fresh_rest1;
+ Ast.inherited = inherited_rest1;
+ Ast.saved_witness = s1}]
+
+ | (Ast.OptStm(stm)::urest,_::rest) ->
+ let l = Ast.get_line stm in
+ let new_rest1 = dots_list urest rest in
+ let new_rest2 = stm::new_rest1 in
+ let (fv_rest1,mfv_rest1,fresh_rest1,inherited_rest1,s1) =
+ varlists new_rest1 in
+ let (fv_rest2,mfv_rest2,fresh_rest2,inherited_rest2,s2) =
+ varlists new_rest2 in
+ [{(Ast.make_term
+ (Ast.Disj
+ [{(Ast.make_term(Ast.DOTS(new_rest2))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest2;
+ Ast.minus_free_vars = mfv_rest2;
+ Ast.fresh_vars = fresh_rest2;
+ Ast.inherited = inherited_rest2;
+ Ast.saved_witness = s2};
+ {(Ast.make_term(Ast.DOTS(new_rest1))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest1;
+ Ast.minus_free_vars = mfv_rest1;
+ Ast.fresh_vars = fresh_rest1;
+ Ast.inherited = inherited_rest1;
+ Ast.saved_witness = s1}])) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest2;
+ Ast.minus_free_vars = mfv_rest2;
+ Ast.fresh_vars = fresh_rest2;
+ Ast.inherited = inherited_rest2;
+ Ast.saved_witness = s2}]
+
+ | ([Ast.Dots(_,_,_,_);Ast.OptStm(stm)],[d1;_]) ->
+ let l = Ast.get_line stm in
+ let fv_stm = Ast.get_fvs stm in
+ let mfv_stm = Ast.get_mfvs stm in
+ let fresh_stm = Ast.get_fresh stm in
+ let inh_stm = Ast.get_inherited stm in
+ let saved_stm = Ast.get_saved stm in
+ let fv_d1 = Ast.get_fvs d1 in
+ let mfv_d1 = Ast.get_mfvs d1 in
+ let fresh_d1 = Ast.get_fresh d1 in
+ let inh_d1 = Ast.get_inherited d1 in
+ let saved_d1 = Ast.get_saved d1 in
+ let fv_both = Common.union_set fv_stm fv_d1 in
+ let mfv_both = Common.union_set mfv_stm mfv_d1 in
+ let fresh_both = Common.union_set fresh_stm fresh_d1 in
+ let inh_both = Common.union_set inh_stm inh_d1 in
+ let saved_both = Common.union_set saved_stm saved_d1 in
+ [d1;
+ {(Ast.make_term
+ (Ast.Disj
+ [{(Ast.make_term(Ast.DOTS([stm]))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_stm;
+ Ast.minus_free_vars = mfv_stm;
+ Ast.fresh_vars = fresh_stm;
+ Ast.inherited = inh_stm;
+ Ast.saved_witness = saved_stm};
+ {(Ast.make_term(Ast.DOTS([d1]))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_d1;
+ Ast.minus_free_vars = mfv_d1;
+ Ast.fresh_vars = fresh_d1;
+ Ast.inherited = inh_d1;
+ Ast.saved_witness = saved_d1}])) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_both;
+ Ast.minus_free_vars = mfv_both;
+ Ast.fresh_vars = fresh_both;
+ Ast.inherited = inh_both;
+ Ast.saved_witness = saved_both}]
+
+ | ([Ast.Nest(_,_,_,_,_);Ast.OptStm(stm)],[d1;_]) ->
+ let l = Ast.get_line stm in
+ let rw = Ast.rewrap stm in
+ let rwd = Ast.rewrap stm in
+ let dots = Ast.Dots(Ast.make_mcode "...",[],[],[]) in
+ [d1;rw(Ast.Disj
+ [rwd(Ast.DOTS([stm]));
+ {(Ast.make_term(Ast.DOTS([rw dots])))
+ with Ast.node_line = l}])]
+
+ | (_::urest,stm::rest) -> stm :: (dots_list urest rest)
+ | _ -> failwith "not possible" in
+
+ let stmtdotsfn r k d =
+ let d = k d in
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(dots_list (List.map Ast.unwrap l) l)
+ | Ast.CIRCLES(l) -> failwith "elimopt: not supported"
+ | Ast.STARS(l) -> failwith "elimopt: not supported") in
+
+ V.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing stmtdotsfn donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* after management *)
+(* We need Guard for the following case:
+<...
+ a
+ <...
+ b
+ ...>
+...>
+foo();
+
+Here the inner <... b ...> should not go past foo. But foo is not the
+"after" of the body of the outer nest, because we don't want to search for
+it in the case where the body of the outer nest ends in something other
+than dots or a nest. *)
+
+(* what is the difference between tail and end??? *)
+
+type after = After of formula | Guard of formula | Tail | End | VeryEnd
+
+let a2n = function After x -> Guard x | a -> a
+
+let print_ctl x =
+ let pp_pred (x,_) = Pretty_print_engine.pp_predicate x in
+ let pp_meta (_,x) = Common.pp x in
+ Pretty_print_ctl.pp_ctl (pp_pred,pp_meta) false x;
+ Format.print_newline()
+
+let print_after = function
+ After ctl -> Printf.printf "After:\n"; print_ctl ctl
+ | Guard ctl -> Printf.printf "Guard:\n"; print_ctl ctl
+ | Tail -> Printf.printf "Tail\n"
+ | VeryEnd -> Printf.printf "Very End\n"
+ | End -> Printf.printf "End\n"
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+let fresh_var _ = string2var "_v"
+let fresh_pos _ = string2var "_pos" (* must be a constant *)
+
+let fresh_metavar _ = "_S"
+
+(* fvinfo is going to end up being from the whole associated statement.
+ it would be better if it were just the free variables in d, but free_vars.ml
+ doesn't keep track of free variables on + code *)
+let make_meta_rule_elem d fvinfo =
+ let nm = fresh_metavar() in
+ Ast.make_meta_rule_elem nm d fvinfo
+
+let get_unquantified quantified vars =
+ List.filter (function x -> not (List.mem x quantified)) vars
+
+let make_seq guard l =
+ let s = guard_to_strict guard in
+ foldr1 (function rest -> function cur -> ctl_and s cur (ctl_ax s rest)) l
+
+let make_seq_after2 guard first rest =
+ let s = guard_to_strict guard in
+ match rest with
+ After rest -> ctl_and s first (ctl_ax s (ctl_ax s rest))
+ | _ -> first
+
+let make_seq_after guard first rest =
+ match rest with
+ After rest -> make_seq guard [first;rest]
+ | _ -> first
+
+let opt_and guard first rest =
+ let s = guard_to_strict guard in
+ match first with
+ None -> rest
+ | Some first -> ctl_and s first rest
+
+let and_after guard first rest =
+ let s = guard_to_strict guard in
+ match rest with After rest -> ctl_and s first rest | _ -> first
+
+let contains_modif =
+ let bind x y = x or y in
+ let option_default = false in
+ let mcode r (_,_,kind,_) =
+ match kind with
+ Ast.MINUS(_,_) -> true
+ | Ast.PLUS -> failwith "not possible"
+ | Ast.CONTEXT(_,info) -> not (info = Ast.NOTHING) in
+ let do_nothing r k e = k e in
+ let rule_elem r k re =
+ let res = k re in
+ match Ast.unwrap re with
+ Ast.FunHeader(bef,_,fninfo,name,lp,params,rp) ->
+ bind (mcode r ((),(),bef,Ast.NoMetaPos)) res
+ | Ast.Decl(bef,_,decl) -> bind (mcode r ((),(),bef,Ast.NoMetaPos)) res
+ | _ -> res in
+ let recursor =
+ V.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing rule_elem do_nothing do_nothing do_nothing do_nothing in
+ recursor.V.combiner_rule_elem
+
+(* code is not a DisjRuleElem *)
+let make_match label guard code =
+ let v = fresh_var() in
+ let matcher = Lib_engine.Match(code) in
+ if contains_modif code && not guard
+ then CTL.Exists(true,v,predmaker guard (matcher,CTL.Modif v) label)
+ else
+ let iso_info = !Flag.track_iso_usage && not (Ast.get_isos code = []) in
+ (match (iso_info,!onlyModif,guard,
+ intersect !used_after (Ast.get_fvs code)) with
+ (false,true,_,[]) | (_,_,true,_) ->
+ predmaker guard (matcher,CTL.Control) label
+ | _ -> CTL.Exists(true,v,predmaker guard (matcher,CTL.UnModif v) label))
+
+let make_raw_match label guard code =
+ predmaker guard (Lib_engine.Match(code),CTL.Control) label
+
+let rec seq_fvs quantified = function
+ [] -> []
+ | fv1::fvs ->
+ let t1fvs = get_unquantified quantified fv1 in
+ let termfvs =
+ List.fold_left Common.union_set []
+ (List.map (get_unquantified quantified) fvs) in
+ let bothfvs = Common.inter_set t1fvs termfvs in
+ let t1onlyfvs = Common.minus_set t1fvs bothfvs in
+ let new_quantified = Common.union_set bothfvs quantified in
+ (t1onlyfvs,bothfvs)::(seq_fvs new_quantified fvs)
+
+let quantify guard =
+ List.fold_right
+ (function cur ->
+ function code -> CTL.Exists (not guard && List.mem cur !saved,cur,code))
+
+let non_saved_quantify =
+ List.fold_right
+ (function cur -> function code -> CTL.Exists (false,cur,code))
+
+let intersectll lst nested_list =
+ List.filter (function x -> List.exists (List.mem x) nested_list) lst
+
+(* --------------------------------------------------------------------- *)
+(* Count depth of braces. The translation of a closed brace appears deeply
+nested within the translation of the sequence term, so the name of the
+paren var has to take into account the names of the nested braces. On the
+other hand the close brace does not escape, so we don't have to take into
+account other paren variable names. *)
+
+(* called repetitively, which is inefficient, but less trouble than adding a
+new field to Seq and FunDecl *)
+let count_nested_braces s =
+ let bind x y = max x y in
+ let option_default = 0 in
+ let stmt_count r k s =
+ match Ast.unwrap s with
+ Ast.Seq(_,_,_,_) | Ast.FunDecl(_,_,_,_,_) -> (k s) + 1
+ | _ -> k s in
+ let donothing r k e = k e in
+ let mcode r x = 0 in
+ let recursor = V.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing stmt_count donothing donothing donothing in
+ let res = string_of_int (recursor.V.combiner_statement s) in
+ string2var ("p"^res)
+
+let labelctr = ref 0
+let get_label_ctr _ =
+ let cur = !labelctr in
+ labelctr := cur + 1;
+ string2var (Printf.sprintf "l%d" cur)
+
+(* --------------------------------------------------------------------- *)
+(* annotate dots with before and after neighbors *)
+
+let print_bef_aft = function
+ Ast.WParen (re,n) ->
+ Printf.printf "bef/aft\n";
+ Pretty_print_cocci.rule_elem "" re;
+ Format.print_newline()
+ | Ast.Other s ->
+ Printf.printf "bef/aft\n";
+ Pretty_print_cocci.statement "" s;
+ Format.print_newline()
+ | Ast.Other_dots d ->
+ Printf.printf "bef/aft\n";
+ Pretty_print_cocci.statement_dots d;
+ Format.print_newline()
+
+(* [] can only occur if we are in a disj, where it comes from a ? In that
+case, we want to use a, which accumulates all of the previous patterns in
+their entirety. *)
+let rec get_before_elem sl a =
+ match Ast.unwrap sl with
+ Ast.DOTS(x) ->
+ let rec loop sl a =
+ match sl with
+ [] -> ([],Common.Right a)
+ | [e] ->
+ let (e,ea) = get_before_e e a in
+ ([e],Common.Left ea)
+ | e::sl ->
+ let (e,ea) = get_before_e e a in
+ let (sl,sla) = loop sl ea in
+ (e::sl,sla) in
+ let (l,a) = loop x a in
+ (Ast.rewrap sl (Ast.DOTS(l)),a)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+and get_before sl a =
+ match get_before_elem sl a with
+ (term,Common.Left x) -> (term,x)
+ | (term,Common.Right x) -> (term,x)
+
+and get_before_whencode wc =
+ List.map
+ (function
+ Ast.WhenNot w -> let (w,_) = get_before w [] in Ast.WhenNot w
+ | Ast.WhenAlways w -> let (w,_) = get_before_e w [] in Ast.WhenAlways w
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x))
+ wc
+
+and get_before_e s a =
+ match Ast.unwrap s with
+ Ast.Dots(d,w,_,aft) ->
+ (Ast.rewrap s (Ast.Dots(d,get_before_whencode w,a,aft)),a)
+ | Ast.Nest(stmt_dots,w,multi,_,aft) ->
+ let w = get_before_whencode w in
+ let (sd,_) = get_before stmt_dots a in
+ let a =
+ List.filter
+ (function
+ Ast.Other a ->
+ let unifies =
+ Unify_ast.unify_statement_dots
+ (Ast.rewrap s (Ast.DOTS([a]))) stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | Ast.Other_dots a ->
+ let unifies = Unify_ast.unify_statement_dots a stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | _ -> true)
+ a in
+ (Ast.rewrap s (Ast.Nest(sd,w,multi,a,aft)),[Ast.Other_dots stmt_dots])
+ | Ast.Disj(stmt_dots_list) ->
+ let (dsl,dsla) =
+ List.split (List.map (function e -> get_before e a) stmt_dots_list) in
+ (Ast.rewrap s (Ast.Disj(dsl)),List.fold_left Common.union_set [] dsla)
+ | Ast.Atomic(ast) ->
+ (match Ast.unwrap ast with
+ Ast.MetaStmt(_,_,_,_) -> (s,[])
+ | _ -> (s,[Ast.Other s]))
+ | Ast.Seq(lbrace,decls,body,rbrace) ->
+ let index = count_nested_braces s in
+ let (de,dea) = get_before decls [Ast.WParen(lbrace,index)] in
+ let (bd,_) = get_before body dea in
+ (Ast.rewrap s (Ast.Seq(lbrace,de,bd,rbrace)),
+ [Ast.WParen(rbrace,index)])
+ | Ast.Define(header,body) ->
+ let (body,_) = get_before body [] in
+ (Ast.rewrap s (Ast.Define(header,body)), [Ast.Other s])
+ | Ast.IfThen(ifheader,branch,aft) ->
+ let (br,_) = get_before_e branch [] in
+ (Ast.rewrap s (Ast.IfThen(ifheader,br,aft)), [Ast.Other s])
+ | Ast.IfThenElse(ifheader,branch1,els,branch2,aft) ->
+ let (br1,_) = get_before_e branch1 [] in
+ let (br2,_) = get_before_e branch2 [] in
+ (Ast.rewrap s (Ast.IfThenElse(ifheader,br1,els,br2,aft)),[Ast.Other s])
+ | Ast.While(header,body,aft) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.While(header,bd,aft)),[Ast.Other s])
+ | Ast.For(header,body,aft) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.For(header,bd,aft)),[Ast.Other s])
+ | Ast.Do(header,body,tail) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.Do(header,bd,tail)),[Ast.Other s])
+ | Ast.Iterator(header,body,aft) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.Iterator(header,bd,aft)),[Ast.Other s])
+ | Ast.Switch(header,lb,cases,rb) ->
+ let cases =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let (body,_) = get_before body [] in
+ Ast.rewrap case_line (Ast.CaseLine(header,body))
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ (Ast.rewrap s (Ast.Switch(header,lb,cases,rb)),[Ast.Other s])
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ let (de,dea) = get_before decls [] in
+ let (bd,_) = get_before body dea in
+ (Ast.rewrap s (Ast.FunDecl(header,lbrace,de,bd,rbrace)),[])
+ | _ -> failwith "get_before_e: not supported"
+
+let rec get_after sl a =
+ match Ast.unwrap sl with
+ Ast.DOTS(x) ->
+ let rec loop sl =
+ match sl with
+ [] -> ([],a)
+ | e::sl ->
+ let (sl,sla) = loop sl in
+ let (e,ea) = get_after_e e sla in
+ (e::sl,ea) in
+ let (l,a) = loop x in
+ (Ast.rewrap sl (Ast.DOTS(l)),a)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+and get_after_whencode a wc =
+ List.map
+ (function
+ Ast.WhenNot w -> let (w,_) = get_after w a (*?*) in Ast.WhenNot w
+ | Ast.WhenAlways w -> let (w,_) = get_after_e w a in Ast.WhenAlways w
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x))
+ wc
+
+and get_after_e s a =
+ match Ast.unwrap s with
+ Ast.Dots(d,w,bef,_) ->
+ (Ast.rewrap s (Ast.Dots(d,get_after_whencode a w,bef,a)),a)
+ | Ast.Nest(stmt_dots,w,multi,bef,_) ->
+ let w = get_after_whencode a w in
+ let (sd,_) = get_after stmt_dots a in
+ let a =
+ List.filter
+ (function
+ Ast.Other a ->
+ let unifies =
+ Unify_ast.unify_statement_dots
+ (Ast.rewrap s (Ast.DOTS([a]))) stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | Ast.Other_dots a ->
+ let unifies = Unify_ast.unify_statement_dots a stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | _ -> true)
+ a in
+ (Ast.rewrap s (Ast.Nest(sd,w,multi,bef,a)),[Ast.Other_dots stmt_dots])
+ | Ast.Disj(stmt_dots_list) ->
+ let (dsl,dsla) =
+ List.split (List.map (function e -> get_after e a) stmt_dots_list) in
+ (Ast.rewrap s (Ast.Disj(dsl)),List.fold_left Common.union_set [] dsla)
+ | Ast.Atomic(ast) ->
+ (match Ast.unwrap ast with
+ Ast.MetaStmt(nm,keep,Ast.SequencibleAfterDots _,i) ->
+ (* check "after" information for metavar optimization *)
+ (* if the error is not desired, could just return [], then
+ the optimization (check for EF) won't take place *)
+ List.iter
+ (function
+ Ast.Other x ->
+ (match Ast.unwrap x with
+ Ast.Dots(_,_,_,_) | Ast.Nest(_,_,_,_,_) ->
+ failwith
+ "dots/nest not allowed before and after stmt metavar"
+ | _ -> ())
+ | Ast.Other_dots x ->
+ (match Ast.undots x with
+ x::_ ->
+ (match Ast.unwrap x with
+ Ast.Dots(_,_,_,_) | Ast.Nest(_,_,_,_,_) ->
+ failwith
+ ("dots/nest not allowed before and after stmt "^
+ "metavar")
+ | _ -> ())
+ | _ -> ())
+ | _ -> ())
+ a;
+ (Ast.rewrap s
+ (Ast.Atomic
+ (Ast.rewrap s
+ (Ast.MetaStmt(nm,keep,Ast.SequencibleAfterDots a,i)))),[])
+ | Ast.MetaStmt(_,_,_,_) -> (s,[])
+ | _ -> (s,[Ast.Other s]))
+ | Ast.Seq(lbrace,decls,body,rbrace) ->
+ let index = count_nested_braces s in
+ let (bd,bda) = get_after body [Ast.WParen(rbrace,index)] in
+ let (de,_) = get_after decls bda in
+ (Ast.rewrap s (Ast.Seq(lbrace,de,bd,rbrace)),
+ [Ast.WParen(lbrace,index)])
+ | Ast.Define(header,body) ->
+ let (body,_) = get_after body a in
+ (Ast.rewrap s (Ast.Define(header,body)), [Ast.Other s])
+ | Ast.IfThen(ifheader,branch,aft) ->
+ let (br,_) = get_after_e branch a in
+ (Ast.rewrap s (Ast.IfThen(ifheader,br,aft)),[Ast.Other s])
+ | Ast.IfThenElse(ifheader,branch1,els,branch2,aft) ->
+ let (br1,_) = get_after_e branch1 a in
+ let (br2,_) = get_after_e branch2 a in
+ (Ast.rewrap s (Ast.IfThenElse(ifheader,br1,els,br2,aft)),[Ast.Other s])
+ | Ast.While(header,body,aft) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.While(header,bd,aft)),[Ast.Other s])
+ | Ast.For(header,body,aft) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.For(header,bd,aft)),[Ast.Other s])
+ | Ast.Do(header,body,tail) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.Do(header,bd,tail)),[Ast.Other s])
+ | Ast.Iterator(header,body,aft) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.Iterator(header,bd,aft)),[Ast.Other s])
+ | Ast.Switch(header,lb,cases,rb) ->
+ let cases =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let (body,_) = get_after body [] in
+ Ast.rewrap case_line (Ast.CaseLine(header,body))
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ (Ast.rewrap s (Ast.Switch(header,lb,cases,rb)),[Ast.Other s])
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ let (bd,bda) = get_after body [] in
+ let (de,_) = get_after decls bda in
+ (Ast.rewrap s (Ast.FunDecl(header,lbrace,de,bd,rbrace)),[])
+ | _ -> failwith "get_after_e: not supported"
+
+let preprocess_dots sl =
+ let (sl,_) = get_before sl [] in
+ let (sl,_) = get_after sl [] in
+ sl
+
+let preprocess_dots_e sl =
+ let (sl,_) = get_before_e sl [] in
+ let (sl,_) = get_after_e sl [] in
+ sl
+
+(* --------------------------------------------------------------------- *)
+(* various return_related things *)
+
+let rec ends_in_return stmt_list =
+ match Ast.unwrap stmt_list with
+ Ast.DOTS(x) ->
+ (match List.rev x with
+ x::_ ->
+ (match Ast.unwrap x with
+ Ast.Atomic(x) ->
+ (match Ast.unwrap x with
+ Ast.Return(_,_) | Ast.ReturnExpr(_,_,_) -> true
+ | _ -> false)
+ | Ast.Disj(disjs) -> List.for_all ends_in_return disjs
+ | _ -> false)
+ | _ -> false)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+(* --------------------------------------------------------------------- *)
+(* expressions *)
+
+let exptymatch l make_match make_guard_match =
+ let pos = fresh_pos() in
+ let matches_guard_matches =
+ List.map
+ (function x ->
+ let pos = Ast.make_mcode pos in
+ (make_match (Ast.set_pos x (Some pos)),
+ make_guard_match (Ast.set_pos x (Some pos))))
+ l in
+ let (matches,guard_matches) = List.split matches_guard_matches in
+ let rec suffixes = function
+ [] -> []
+ | x::xs -> xs::(suffixes xs) in
+ let prefixes = List.rev (suffixes (List.rev guard_matches)) in
+ let info = (* not null *)
+ List.map2
+ (function matcher ->
+ function negates ->
+ CTL.Exists
+ (false,pos,
+ ctl_and CTL.NONSTRICT matcher
+ (ctl_not
+ (ctl_uncheck (List.fold_left ctl_or_fl CTL.False negates)))))
+ matches prefixes in
+ CTL.InnerAnd(List.fold_left ctl_or_fl CTL.False (List.rev info))
+
+(* code might be a DisjRuleElem, in which case we break it apart
+ code might contain an Exp or Ty
+ this one pushes the quantifier inwards *)
+let do_re_matches label guard res quantified minus_quantified =
+ let make_guard_match x =
+ let stmt_fvs = Ast.get_mfvs x in
+ let fvs = get_unquantified minus_quantified stmt_fvs in
+ non_saved_quantify fvs (make_match None true x) in
+ let make_match x =
+ let stmt_fvs = Ast.get_fvs x in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard fvs (make_match None guard x) in
+ ctl_and CTL.NONSTRICT (label_pred_maker label)
+ (match List.map Ast.unwrap res with
+ [] -> failwith "unexpected empty disj"
+ | Ast.Exp(e)::rest -> exptymatch res make_match make_guard_match
+ | Ast.Ty(t)::rest -> exptymatch res make_match make_guard_match
+ | all ->
+ if List.exists (function Ast.Exp(_) | Ast.Ty(_) -> true | _ -> false)
+ all
+ then failwith "unexpected exp or ty";
+ List.fold_left ctl_seqor CTL.False
+ (List.rev (List.map make_match res)))
+
+(* code might be a DisjRuleElem, in which case we break it apart
+ code doesn't contain an Exp or Ty
+ this one is for use when it is not practical to push the quantifier inwards
+ *)
+let header_match label guard code : ('a, Ast.meta_name, 'b) CTL.generic_ctl =
+ match Ast.unwrap code with
+ Ast.DisjRuleElem(res) ->
+ let make_match = make_match None guard in
+ let orop = if guard then ctl_or else ctl_seqor in
+ ctl_and CTL.NONSTRICT (label_pred_maker label)
+ (List.fold_left orop CTL.False (List.map make_match res))
+ | _ -> make_match label guard code
+
+(* --------------------------------------------------------------------- *)
+(* control structures *)
+
+let end_control_structure fvs header body after_pred
+ after_checks no_after_checks (afvs,afresh,ainh,aft) after label guard =
+ (* aft indicates what is added after the whole if, which has to be added
+ to the endif node *)
+ let (aft_needed,after_branch) =
+ match aft with
+ Ast.CONTEXT(_,Ast.NOTHING) ->
+ (false,make_seq_after2 guard after_pred after)
+ | _ ->
+ let match_endif =
+ make_match label guard
+ (make_meta_rule_elem aft (afvs,afresh,ainh)) in
+ (true,
+ make_seq_after guard after_pred
+ (After(make_seq_after guard match_endif after))) in
+ let body = body after_branch in
+ let s = guard_to_strict guard in
+ (* the code *)
+ quantify guard fvs
+ (ctl_and s header
+ (opt_and guard
+ (match (after,aft_needed) with
+ (After _,_) (* pattern doesn't end here *)
+ | (_,true) (* + code added after *) -> after_checks
+ | _ -> no_after_checks)
+ (ctl_ax_absolute s body)))
+
+let ifthen ifheader branch ((afvs,_,_,_) as aft) after
+ quantified minus_quantified label llabel slabel recurse make_match guard =
+(* "if (test) thn" becomes:
+ if(test) & AX((TrueBranch & AX thn) v FallThrough v After)
+
+ "if (test) thn; after" becomes:
+ if(test) & AX((TrueBranch & AX thn) v FallThrough v (After & AXAX after))
+ & EX After
+*)
+ (* free variables *)
+ let (efvs,bfvs) =
+ match seq_fvs quantified
+ [Ast.get_fvs ifheader;Ast.get_fvs branch;afvs] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_quantified = Common.union_set bfvs quantified in
+ let (mefvs,mbfvs) =
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs ifheader;Ast.get_mfvs branch;[]] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_mquantified = Common.union_set mbfvs minus_quantified in
+ (* if header *)
+ let if_header = quantify guard efvs (make_match ifheader) in
+ (* then branch and after *)
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let true_branch =
+ make_seq guard
+ [truepred label; recurse branch Tail new_quantified new_mquantified
+ (Some (lv,used)) llabel slabel guard] in
+ let after_pred = aftpred label in
+ let or_cases after_branch =
+ ctl_or true_branch (ctl_or (fallpred label) after_branch) in
+ let (if_header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and CTL.NONSTRICT(*???*) if_header label_pred,
+ (function body -> quantify true [lv] body))
+ else (if_header,function x -> x) in
+ wrapper
+ (end_control_structure bfvs if_header or_cases after_pred
+ (Some(ctl_ex after_pred)) None aft after label guard)
+
+let ifthenelse ifheader branch1 els branch2 ((afvs,_,_,_) as aft) after
+ quantified minus_quantified label llabel slabel recurse make_match guard =
+(* "if (test) thn else els" becomes:
+ if(test) & AX((TrueBranch & AX thn) v
+ (FalseBranch & AX (else & AX els)) v After)
+ & EX FalseBranch
+
+ "if (test) thn else els; after" becomes:
+ if(test) & AX((TrueBranch & AX thn) v
+ (FalseBranch & AX (else & AX els)) v
+ (After & AXAX after))
+ & EX FalseBranch
+ & EX After
+*)
+ (* free variables *)
+ let (e1fvs,b1fvs,s1fvs) =
+ match seq_fvs quantified
+ [Ast.get_fvs ifheader;Ast.get_fvs branch1;afvs] with
+ [(e1fvs,b1fvs);(s1fvs,b1afvs);_] ->
+ (e1fvs,Common.union_set b1fvs b1afvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let (e2fvs,b2fvs,s2fvs) =
+ (* fvs on else? *)
+ match seq_fvs quantified
+ [Ast.get_fvs ifheader;Ast.get_fvs branch2;afvs] with
+ [(e2fvs,b2fvs);(s2fvs,b2afvs);_] ->
+ (e2fvs,Common.union_set b2fvs b2afvs,s2fvs)
+ | _ -> failwith "not possible" in
+ let bothfvs = union (union b1fvs b2fvs) (intersect s1fvs s2fvs) in
+ let exponlyfvs = intersect e1fvs e2fvs in
+ let new_quantified = union bothfvs quantified in
+ (* minus free variables *)
+ let (me1fvs,mb1fvs,ms1fvs) =
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs ifheader;Ast.get_mfvs branch1;[]] with
+ [(e1fvs,b1fvs);(s1fvs,b1afvs);_] ->
+ (e1fvs,Common.union_set b1fvs b1afvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let (me2fvs,mb2fvs,ms2fvs) =
+ (* fvs on else? *)
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs ifheader;Ast.get_mfvs branch2;[]] with
+ [(e2fvs,b2fvs);(s2fvs,b2afvs);_] ->
+ (e2fvs,Common.union_set b2fvs b2afvs,s2fvs)
+ | _ -> failwith "not possible" in
+ let mbothfvs = union (union mb1fvs mb2fvs) (intersect ms1fvs ms2fvs) in
+ let new_mquantified = union mbothfvs minus_quantified in
+ (* if header *)
+ let if_header = quantify guard exponlyfvs (make_match ifheader) in
+ (* then and else branches *)
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let true_branch =
+ make_seq guard
+ [truepred label; recurse branch1 Tail new_quantified new_mquantified
+ (Some (lv,used)) llabel slabel guard] in
+ let false_branch =
+ make_seq guard
+ [falsepred label; make_match els;
+ recurse branch2 Tail new_quantified new_mquantified
+ (Some (lv,used)) llabel slabel guard] in
+ let after_pred = aftpred label in
+ let or_cases after_branch =
+ ctl_or true_branch (ctl_or false_branch after_branch) in
+ let s = guard_to_strict guard in
+ let (if_header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and CTL.NONSTRICT(*???*) if_header label_pred,
+ (function body -> quantify true [lv] body))
+ else (if_header,function x -> x) in
+ wrapper
+ (end_control_structure bothfvs if_header or_cases after_pred
+ (Some(ctl_and s (ctl_ex (falsepred label)) (ctl_ex after_pred)))
+ (Some(ctl_ex (falsepred label)))
+ aft after label guard)
+
+let forwhile header body ((afvs,_,_,_) as aft) after
+ quantified minus_quantified label recurse make_match guard =
+ let process _ =
+ (* the translation in this case is similar to that of an if with no else *)
+ (* free variables *)
+ let (efvs,bfvs) =
+ match seq_fvs quantified [Ast.get_fvs header;Ast.get_fvs body;afvs] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_quantified = Common.union_set bfvs quantified in
+ (* minus free variables *)
+ let (mefvs,mbfvs) =
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs header;Ast.get_mfvs body;[]] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_mquantified = Common.union_set mbfvs minus_quantified in
+ (* loop header *)
+ let header = quantify guard efvs (make_match header) in
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let body =
+ make_seq guard
+ [inlooppred label;
+ recurse body Tail new_quantified new_mquantified
+ (Some (lv,used)) (Some (lv,used)) None guard] in
+ let after_pred = fallpred label in
+ let or_cases after_branch = ctl_or body after_branch in
+ let (header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and CTL.NONSTRICT(*???*) header label_pred,
+ (function body -> quantify true [lv] body))
+ else (header,function x -> x) in
+ wrapper
+ (end_control_structure bfvs header or_cases after_pred
+ (Some(ctl_ex after_pred)) None aft after label guard) in
+ match (Ast.unwrap body,aft) with
+ (Ast.Atomic(re),(_,_,_,Ast.CONTEXT(_,Ast.NOTHING))) ->
+ (match Ast.unwrap re with
+ Ast.MetaStmt((_,_,Ast.CONTEXT(_,Ast.NOTHING),_),
+ Type_cocci.Unitary,_,false) ->
+ let (efvs) =
+ match seq_fvs quantified [Ast.get_fvs header] with
+ [(efvs,_)] -> efvs
+ | _ -> failwith "not possible" in
+ quantify guard efvs (make_match header)
+ | _ -> process())
+ | _ -> process()
+
+(* --------------------------------------------------------------------- *)
+(* statement metavariables *)
+
+(* issue: an S metavariable that is not an if branch/loop body
+ should not match an if branch/loop body, so check that the labels
+ of the nodes before the first node matched by the S are different
+ from the label of the first node matched by the S *)
+let sequencibility body label_pred process_bef_aft = function
+ Ast.Sequencible | Ast.SequencibleAfterDots [] ->
+ body
+ (function x ->
+ (ctl_and CTL.NONSTRICT (ctl_not (ctl_back_ax label_pred)) x))
+ | Ast.SequencibleAfterDots l ->
+ (* S appears after some dots. l is the code that comes after the S.
+ want to search for that first, because S can match anything, while
+ the stuff after is probably more restricted *)
+ let afts = List.map process_bef_aft l in
+ let ors = foldl1 ctl_or afts in
+ ctl_and CTL.NONSTRICT
+ (ctl_ef (ctl_and CTL.NONSTRICT ors (ctl_back_ax label_pred)))
+ (body
+ (function x ->
+ ctl_and CTL.NONSTRICT (ctl_not (ctl_back_ax label_pred)) x))
+ | Ast.NotSequencible -> body (function x -> x)
+
+let svar_context_with_add_after stmt s label quantified d ast
+ seqible after process_bef_aft guard fvinfo =
+ let label_var = (*fresh_label_var*) string2var "_lab" in
+ let label_pred =
+ CTL.Pred (Lib_engine.Label(label_var),CTL.Control) in
+ let prelabel_pred =
+ CTL.Pred (Lib_engine.PrefixLabel(label_var),CTL.Control) in
+ let matcher d = make_match None guard (make_meta_rule_elem d fvinfo) in
+ let full_metamatch = matcher d in
+ let first_metamatch =
+ matcher
+ (match d with
+ Ast.CONTEXT(pos,Ast.BEFOREAFTER(bef,_)) ->
+ Ast.CONTEXT(pos,Ast.BEFORE(bef))
+ | Ast.CONTEXT(pos,_) -> Ast.CONTEXT(pos,Ast.NOTHING)
+ | Ast.MINUS(_,_) | Ast.PLUS -> failwith "not possible") in
+ let middle_metamatch =
+ matcher
+ (match d with
+ Ast.CONTEXT(pos,_) -> Ast.CONTEXT(pos,Ast.NOTHING)
+ | Ast.MINUS(_,_) | Ast.PLUS -> failwith "not possible") in
+ let last_metamatch =
+ matcher
+ (match d with
+ Ast.CONTEXT(pos,Ast.BEFOREAFTER(_,aft)) ->
+ Ast.CONTEXT(pos,Ast.AFTER(aft))
+ | Ast.CONTEXT(_,_) -> d
+ | Ast.MINUS(_,_) | Ast.PLUS -> failwith "not possible") in
+
+ let rest_nodes =
+ ctl_and CTL.NONSTRICT middle_metamatch prelabel_pred in
+ let left_or = (* the whole statement is one node *)
+ make_seq guard
+ [full_metamatch; and_after guard (ctl_not prelabel_pred) after] in
+ let right_or = (* the statement covers multiple nodes *)
+ make_seq guard
+ [first_metamatch;
+ ctl_au CTL.NONSTRICT
+ rest_nodes
+ (make_seq guard
+ [ctl_and CTL.NONSTRICT last_metamatch label_pred;
+ and_after guard
+ (ctl_not prelabel_pred) after])] in
+ let body f =
+ ctl_and CTL.NONSTRICT label_pred
+ (f (ctl_and CTL.NONSTRICT
+ (make_raw_match label false ast) (ctl_or left_or right_or))) in
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard (label_var::fvs)
+ (sequencibility body label_pred process_bef_aft seqible)
+
+let svar_minus_or_no_add_after stmt s label quantified d ast
+ seqible after process_bef_aft guard fvinfo =
+ let label_var = (*fresh_label_var*) string2var "_lab" in
+ let label_pred =
+ CTL.Pred (Lib_engine.Label(label_var),CTL.Control) in
+ let prelabel_pred =
+ CTL.Pred (Lib_engine.PrefixLabel(label_var),CTL.Control) in
+ let matcher d = make_match None guard (make_meta_rule_elem d fvinfo) in
+ let pure_d =
+ (* don't have to put anything before the beginning, so don't have to
+ distinguish the first node. so don't have to bother about paths,
+ just use the label. label ensures that found nodes match up with
+ what they should because it is in the lhs of the andany. *)
+ match d with
+ Ast.MINUS(pos,[]) -> true
+ | Ast.CONTEXT(pos,Ast.NOTHING) -> true
+ | _ -> false in
+ let ender =
+ match (pure_d,after) with
+ (true,Tail) | (true,End) | (true,VeryEnd) ->
+ (* the label sharing makes it safe to use AndAny *)
+ CTL.HackForStmt(CTL.FORWARD,CTL.NONSTRICT,
+ ctl_and CTL.NONSTRICT label_pred
+ (make_raw_match label false ast),
+ ctl_and CTL.NONSTRICT (matcher d) prelabel_pred)
+ | _ ->
+ (* more safe but less efficient *)
+ let first_metamatch = matcher d in
+ let rest_metamatch =
+ matcher
+ (match d with
+ Ast.MINUS(pos,_) -> Ast.MINUS(pos,[])
+ | Ast.CONTEXT(pos,_) -> Ast.CONTEXT(pos,Ast.NOTHING)
+ | Ast.PLUS -> failwith "not possible") in
+ let rest_nodes = ctl_and CTL.NONSTRICT rest_metamatch prelabel_pred in
+ let last_node = and_after guard (ctl_not prelabel_pred) after in
+ (ctl_and CTL.NONSTRICT (make_raw_match label false ast)
+ (make_seq guard
+ [first_metamatch;
+ ctl_au CTL.NONSTRICT rest_nodes last_node])) in
+ let body f = ctl_and CTL.NONSTRICT label_pred (f ender) in
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard (label_var::fvs)
+ (sequencibility body label_pred process_bef_aft seqible)
+
+(* --------------------------------------------------------------------- *)
+(* dots and nests *)
+
+let dots_au is_strict toend label s wrapcode x seq_after y quantifier =
+ let matchgoto = gotopred None in
+ let matchbreak =
+ make_match None false
+ (wrapcode
+ (Ast.Break(Ast.make_mcode "break",Ast.make_mcode ";"))) in
+ let matchcontinue =
+ make_match None false
+ (wrapcode
+ (Ast.Continue(Ast.make_mcode "continue",Ast.make_mcode ";"))) in
+ let stop_early v =
+ if !exists = Exists
+ then CTL.False
+ else if toend
+ then CTL.Or(aftpred label,exitpred label)
+ else if is_strict
+ then aftpred label
+ else
+ let lv = get_label_ctr() in
+ let labelpred = CTL.Pred(Lib_engine.Label lv,CTL.Control) in
+ let preflabelpred = label_pred_maker (Some (lv,ref true)) in
+ ctl_or (aftpred label)
+ (quantify false [lv]
+ (ctl_and CTL.NONSTRICT
+ (ctl_and CTL.NONSTRICT (truepred label) labelpred)
+ (ctl_au CTL.NONSTRICT
+ (ctl_and CTL.NONSTRICT (ctl_not v) preflabelpred)
+ (ctl_and CTL.NONSTRICT preflabelpred
+ (ctl_or (retpred None)
+ (if !Flag_engine.only_return_is_error_exit
+ then CTL.True
+ else
+ (ctl_or matchcontinue
+ (ctl_and CTL.NONSTRICT
+ (ctl_or matchgoto matchbreak)
+ (ctl_ag s (ctl_not seq_after)))))))))) in
+ let v = get_let_ctr() in
+ let op = if quantifier = !exists then ctl_au else ctl_anti_au in
+ op s x (CTL.Let(v,y,ctl_or (CTL.Ref v) (stop_early (CTL.Ref v))))
+
+let rec dots_and_nests plus nest whencodes bef aft dotcode after label
+ process_bef_aft statement_list statement guard wrapcode =
+ let ctl_and_ns = ctl_and CTL.NONSTRICT in
+ (* proces bef_aft *)
+ let shortest l =
+ List.fold_left ctl_or_fl CTL.False (List.map process_bef_aft l) in
+ let bef_aft = (* to be negated *)
+ try
+ let _ =
+ List.find
+ (function Ast.WhenModifier(Ast.WhenAny) -> true | _ -> false)
+ whencodes in
+ CTL.False
+ with Not_found -> shortest (Common.union_set bef aft) in
+ let is_strict =
+ List.exists
+ (function Ast.WhenModifier(Ast.WhenStrict) -> true | _ -> false)
+ whencodes in
+ let check_quantifier quant other =
+ if List.exists
+ (function Ast.WhenModifier(x) -> x = quant | _ -> false)
+ whencodes
+ then
+ if List.exists
+ (function Ast.WhenModifier(x) -> x = other | _ -> false)
+ whencodes
+ then failwith "inconsistent annotation on dots"
+ else true
+ else false in
+ let quantifier =
+ if check_quantifier Ast.WhenExists Ast.WhenForall
+ then Exists
+ else
+ if check_quantifier Ast.WhenExists Ast.WhenForall
+ then Forall
+ else !exists in
+ (* the following is used when we find a goto, etc and consider accepting
+ without finding the rest of the pattern *)
+ let aft = shortest aft in
+ (* process whencode *)
+ let labelled = label_pred_maker label in
+ let whencodes arg =
+ let (poswhen,negwhen) =
+ List.fold_left
+ (function (poswhen,negwhen) ->
+ function
+ Ast.WhenNot whencodes ->
+ (poswhen,ctl_or (statement_list whencodes) negwhen)
+ | Ast.WhenAlways stm ->
+ (ctl_and CTL.NONSTRICT (statement stm) poswhen,negwhen)
+ | Ast.WhenModifier(_) -> (poswhen,negwhen))
+ (CTL.True,bef_aft) (List.rev whencodes) in
+ let poswhen = ctl_and_ns arg poswhen in
+ let negwhen =
+(* if !exists
+ then*)
+ (* add in After, because it's not part of the program *)
+ ctl_or (aftpred label) negwhen
+ (*else negwhen*) in
+ ctl_and_ns poswhen (ctl_not negwhen) in
+ (* process dot code, if any *)
+ let dotcode =
+ match (dotcode,guard) with
+ (None,_) | (_,true) -> CTL.True
+ | (Some dotcode,_) -> dotcode in
+ (* process nest code, if any *)
+ (* whencode goes in the negated part of the nest; if no nest, just goes
+ on the "true" in between code *)
+ let plus_var = if plus then get_label_ctr() else string2var "" in
+ let plus_var2 = if plus then get_label_ctr() else string2var "" in
+ let ornest =
+ match (nest,guard && not plus) with
+ (None,_) | (_,true) -> whencodes CTL.True
+ | (Some nest,false) ->
+ let v = get_let_ctr() in
+ let is_plus x =
+ if plus
+ then
+ (* the idea is that BindGood is sort of a witness; a witness to
+ having found the subterm in at least one place. If there is
+ not a witness, then there is a risk that it will get thrown
+ away, if it is merged with a node that has an empty
+ environment. See tests/nestplus. But this all seems
+ rather suspicious *)
+ CTL.And(CTL.NONSTRICT,x,
+ CTL.Exists(true,plus_var2,
+ CTL.Pred(Lib_engine.BindGood(plus_var),
+ CTL.Modif plus_var2)))
+ else x in
+ CTL.Let(v,nest,
+ CTL.Or(is_plus (CTL.Ref v),
+ whencodes (CTL.Not(ctl_uncheck (CTL.Ref v))))) in
+ let plus_modifier x =
+ if plus
+ then
+ CTL.Exists
+ (false,plus_var,
+ (CTL.And
+ (CTL.NONSTRICT,x,
+ CTL.Not(CTL.Pred(Lib_engine.BindBad(plus_var),CTL.Control)))))
+ else x in
+
+ let ender =
+ match after with
+ After f -> f
+ | Guard f -> ctl_uncheck f
+ | VeryEnd ->
+ let exit = endpred label in
+ let errorexit = exitpred label in
+ ctl_or exit errorexit
+ (* not at all sure what the next two mean... *)
+ | End -> CTL.True
+ | Tail ->
+ (match label with
+ Some (lv,used) -> used := true;
+ ctl_or (CTL.Pred(Lib_engine.Label lv,CTL.Control))
+ (ctl_back_ex (ctl_or (retpred label) (gotopred label)))
+ | None -> endpred label)
+ (* was the following, but not clear why sgrep should allow
+ incomplete patterns
+ let exit = endpred label in
+ let errorexit = exitpred label in
+ if !exists
+ then ctl_or exit errorexit (* end anywhere *)
+ else exit (* end at the real end of the function *) *) in
+ plus_modifier
+ (dots_au is_strict ((after = Tail) or (after = VeryEnd))
+ label (guard_to_strict guard) wrapcode
+ (ctl_and_ns dotcode (ctl_and_ns ornest labelled))
+ aft ender quantifier)
+
+(* --------------------------------------------------------------------- *)
+(* the main translation loop *)
+
+let rec statement_list stmt_list after quantified minus_quantified
+ label llabel slabel dots_before guard =
+ let isdots x =
+ (* include Disj to be on the safe side *)
+ match Ast.unwrap x with
+ Ast.Dots _ | Ast.Nest _ | Ast.Disj _ -> true | _ -> false in
+ let compute_label l e db = if db or isdots e then l else None in
+ match Ast.unwrap stmt_list with
+ Ast.DOTS(x) ->
+ let rec loop quantified minus_quantified dots_before label llabel slabel
+ = function
+ ([],_,_) -> (match after with After f -> f | _ -> CTL.True)
+ | ([e],_,_) ->
+ statement e after quantified minus_quantified
+ (compute_label label e dots_before)
+ llabel slabel guard
+ | (e::sl,fv::fvs,mfv::mfvs) ->
+ let shared = intersectll fv fvs in
+ let unqshared = get_unquantified quantified shared in
+ let new_quantified = Common.union_set unqshared quantified in
+ let minus_shared = intersectll mfv mfvs in
+ let munqshared =
+ get_unquantified minus_quantified minus_shared in
+ let new_mquantified =
+ Common.union_set munqshared minus_quantified in
+ quantify guard unqshared
+ (statement e
+ (After
+ (let (label1,llabel1,slabel1) =
+ match Ast.unwrap e with
+ Ast.Atomic(re) ->
+ (match Ast.unwrap re with
+ Ast.Goto _ -> (None,None,None)
+ | _ -> (label,llabel,slabel))
+ | _ -> (label,llabel,slabel) in
+ loop new_quantified new_mquantified (isdots e)
+ label1 llabel1 slabel1
+ (sl,fvs,mfvs)))
+ new_quantified new_mquantified
+ (compute_label label e dots_before) llabel slabel guard)
+ | _ -> failwith "not possible" in
+ loop quantified minus_quantified dots_before
+ label llabel slabel
+ (x,List.map Ast.get_fvs x,List.map Ast.get_mfvs x)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+(* llabel is the label of the enclosing loop and slabel is the label of the
+ enclosing switch *)
+and statement stmt after quantified minus_quantified
+ label llabel slabel guard =
+ let ctl_au = ctl_au CTL.NONSTRICT in
+ let ctl_ax = ctl_ax CTL.NONSTRICT in
+ let ctl_and = ctl_and CTL.NONSTRICT in
+ let make_seq = make_seq guard in
+ let make_seq_after = make_seq_after guard in
+ let real_make_match = make_match in
+ let make_match = header_match label guard in
+
+ let dots_done = ref false in (* hack for dots cases we can easily handle *)
+
+ let term =
+ match Ast.unwrap stmt with
+ Ast.Atomic(ast) ->
+ (match Ast.unwrap ast with
+ (* the following optimisation is not a good idea, because when S
+ is alone, we would like it not to match a declaration.
+ this makes more matching for things like when (...) S, but perhaps
+ that matching is not so costly anyway *)
+ (*Ast.MetaStmt(_,Type_cocci.Unitary,_,false) when guard -> CTL.True*)
+ | Ast.MetaStmt((s,_,(Ast.CONTEXT(_,Ast.BEFOREAFTER(_,_)) as d),_),
+ keep,seqible,_)
+ | Ast.MetaStmt((s,_,(Ast.CONTEXT(_,Ast.AFTER(_)) as d),_),
+ keep,seqible,_)->
+ svar_context_with_add_after stmt s label quantified d ast seqible
+ after
+ (process_bef_aft quantified minus_quantified
+ label llabel slabel true)
+ guard
+ (Ast.get_fvs stmt, Ast.get_fresh stmt, Ast.get_inherited stmt)
+
+ | Ast.MetaStmt((s,_,d,_),keep,seqible,_) ->
+ svar_minus_or_no_add_after stmt s label quantified d ast seqible
+ after
+ (process_bef_aft quantified minus_quantified
+ label llabel slabel true)
+ guard
+ (Ast.get_fvs stmt, Ast.get_fresh stmt, Ast.get_inherited stmt)
+
+ | _ ->
+ let term =
+ match Ast.unwrap ast with
+ Ast.DisjRuleElem(res) ->
+ do_re_matches label guard res quantified minus_quantified
+ | Ast.Exp(_) | Ast.Ty(_) ->
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ CTL.InnerAnd(quantify guard fvs (make_match ast))
+ | _ ->
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard fvs (make_match ast) in
+ match Ast.unwrap ast with
+ Ast.Break(brk,semi) ->
+ (match (llabel,slabel) with
+ (_,Some(lv,used)) -> (* use switch label if there is one *)
+ ctl_and term (bclabel_pred_maker slabel)
+ | _ -> ctl_and term (bclabel_pred_maker llabel))
+ | Ast.Continue(brk,semi) -> ctl_and term (bclabel_pred_maker llabel)
+ | Ast.Return((_,info,retmc,pos),(_,_,semmc,_)) ->
+ (* discard pattern that comes after return *)
+ let normal_res = make_seq_after term after in
+ (* the following code tries to propagate the modifications on
+ return; to a close brace, in the case where the final return
+ is absent *)
+ let new_mc =
+ match (retmc,semmc) with
+ (Ast.MINUS(_,l1),Ast.MINUS(_,l2)) when !Flag.sgrep_mode2 ->
+ (* in sgrep mode, we can propagate the - *)
+ Some (Ast.MINUS(Ast.NoPos,l1@l2))
+ | (Ast.MINUS(_,l1),Ast.MINUS(_,l2))
+ | (Ast.CONTEXT(_,Ast.BEFORE(l1)),
+ Ast.CONTEXT(_,Ast.AFTER(l2))) ->
+ Some (Ast.CONTEXT(Ast.NoPos,Ast.BEFORE(l1@l2)))
+ | (Ast.CONTEXT(_,Ast.BEFORE(_)),Ast.CONTEXT(_,Ast.NOTHING))
+ | (Ast.CONTEXT(_,Ast.NOTHING),Ast.CONTEXT(_,Ast.NOTHING)) ->
+ Some retmc
+ | (Ast.CONTEXT(_,Ast.NOTHING),Ast.CONTEXT(_,Ast.AFTER(l))) ->
+ Some (Ast.CONTEXT(Ast.NoPos,Ast.BEFORE(l)))
+ | _ -> None in
+ let ret = Ast.make_mcode "return" in
+ let edots =
+ Ast.rewrap ast (Ast.Edots(Ast.make_mcode "...",None)) in
+ let semi = Ast.make_mcode ";" in
+ let simple_return =
+ make_match(Ast.rewrap ast (Ast.Return(ret,semi))) in
+ let return_expr =
+ make_match(Ast.rewrap ast (Ast.ReturnExpr(ret,edots,semi))) in
+ (match new_mc with
+ Some new_mc ->
+ let exit = endpred None in
+ let mod_rbrace =
+ Ast.rewrap ast (Ast.SeqEnd (("}",info,new_mc,pos))) in
+ let stripped_rbrace =
+ Ast.rewrap ast (Ast.SeqEnd(Ast.make_mcode "}")) in
+ ctl_or normal_res
+ (ctl_and (make_match mod_rbrace)
+ (ctl_and
+ (ctl_back_ax
+ (ctl_not
+ (ctl_uncheck
+ (ctl_or simple_return return_expr))))
+ (ctl_au
+ (make_match stripped_rbrace)
+ (* error exit not possible; it is in the middle
+ of code, so a return is needed *)
+ exit)))
+ | _ ->
+ (* some change in the middle of the return, so have to
+ find an actual return *)
+ normal_res)
+ | _ ->
+ (* should try to deal with the dots_bef_aft problem elsewhere,
+ but don't have the courage... *)
+ let term =
+ if guard
+ then term
+ else
+ do_between_dots stmt term End
+ quantified minus_quantified label llabel slabel guard in
+ dots_done := true;
+ make_seq_after term after)
+ | Ast.Seq(lbrace,decls,body,rbrace) ->
+ let (lbfvs,b1fvs,b2fvs,b3fvs,rbfvs) =
+ match
+ seq_fvs quantified
+ [Ast.get_fvs lbrace;Ast.get_fvs decls;
+ Ast.get_fvs body;Ast.get_fvs rbrace]
+ with
+ [(lbfvs,b1fvs);(_,b2fvs);(_,b3fvs);(rbfvs,_)] ->
+ (lbfvs,b1fvs,b2fvs,b3fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let (mlbfvs,mb1fvs,mb2fvs,mb3fvs,mrbfvs) =
+ match
+ seq_fvs minus_quantified
+ [Ast.get_mfvs lbrace;Ast.get_mfvs decls;
+ Ast.get_mfvs body;Ast.get_mfvs rbrace]
+ with
+ [(lbfvs,b1fvs);(_,b2fvs);(_,b3fvs);(rbfvs,_)] ->
+ (lbfvs,b1fvs,b2fvs,b3fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let pv = count_nested_braces stmt in
+ let lv = get_label_ctr() in
+ let paren_pred = CTL.Pred(Lib_engine.Paren pv,CTL.Control) in
+ let label_pred = CTL.Pred(Lib_engine.Label lv,CTL.Control) in
+ let start_brace =
+ ctl_and
+ (quantify guard lbfvs (make_match lbrace))
+ (ctl_and paren_pred label_pred) in
+ let end_brace =
+ (* label is not needed; paren_pred is enough *)
+ ctl_and
+ (quantify guard rbfvs (real_make_match None guard rbrace))
+ paren_pred in
+ let new_quantified2 =
+ Common.union_set b1fvs (Common.union_set b2fvs quantified) in
+ let new_quantified3 = Common.union_set b3fvs new_quantified2 in
+ let new_mquantified2 =
+ Common.union_set mb1fvs (Common.union_set mb2fvs minus_quantified) in
+ let new_mquantified3 = Common.union_set mb3fvs new_mquantified2 in
+ let pattern_as_given =
+ let new_quantified2 = Common.union_set [pv] new_quantified2 in
+ let new_quantified3 = Common.union_set [pv] new_quantified3 in
+ quantify true [pv;lv]
+ (quantify guard b1fvs
+ (make_seq
+ [start_brace;
+ quantify guard b2fvs
+ (statement_list decls
+ (After
+ (quantify guard b3fvs
+ (statement_list body
+ (After (make_seq_after end_brace after))
+ new_quantified3 new_mquantified3
+ (Some (lv,ref true)) (* label mostly useful *)
+ llabel slabel true guard)))
+ new_quantified2 new_mquantified2
+ (Some (lv,ref true)) llabel slabel false guard)])) in
+ if ends_in_return body
+ then
+ (* matching error handling code *)
+ (* Cases:
+ 1. The pattern as given
+ 2. A goto, and then some close braces, and then the pattern as
+ given, but without the braces (only possible if there are no
+ decls, and open and close braces are unmodified)
+ 3. Part of the pattern as given, then a goto, and then the rest
+ of the pattern. For this case, we just check that all paths have
+ a goto within the current braces. checking for a goto at every
+ point in the pattern seems expensive and not worthwhile. *)
+ let pattern2 =
+ let empty_rbrace =
+ match Ast.unwrap rbrace with
+ Ast.SeqEnd((data,info,_,pos)) ->
+ Ast.rewrap rbrace(Ast.SeqEnd(Ast.make_mcode data))
+ | _ -> failwith "unexpected close brace" in
+ let body = preprocess_dots body in (* redo, to drop braces *)
+ make_seq
+ [gotopred label;
+ ctl_au
+ (make_match empty_rbrace)
+ (ctl_ax (* skip the destination label *)
+ (quantify guard b3fvs
+ (statement_list body End
+ new_quantified3 new_mquantified3 None llabel slabel
+ true guard)))] in
+ let pattern3 =
+ let new_quantified2 = Common.union_set [pv] new_quantified2 in
+ let new_quantified3 = Common.union_set [pv] new_quantified3 in
+ quantify true [pv;lv]
+ (quantify guard b1fvs
+ (make_seq
+ [start_brace;
+ ctl_and
+ (CTL.AU (* want AF even for sgrep *)
+ (CTL.FORWARD,CTL.STRICT,
+ CTL.Pred(Lib_engine.PrefixLabel(lv),CTL.Control),
+ ctl_and (* brace must be eventually after goto *)
+ (gotopred (Some (lv,ref true)))
+ (* want AF even for sgrep *)
+ (CTL.AF(CTL.FORWARD,CTL.STRICT,end_brace))))
+ (quantify guard b2fvs
+ (statement_list decls
+ (After
+ (quantify guard b3fvs
+ (statement_list body Tail
+ (*After
+ (make_seq_after
+ nopv_end_brace after)*)
+ new_quantified3 new_mquantified3
+ None llabel slabel true guard)))
+ new_quantified2 new_mquantified2
+ (Some (lv,ref true))
+ llabel slabel false guard))])) in
+ ctl_or pattern_as_given
+ (match Ast.unwrap decls with
+ Ast.DOTS([]) -> ctl_or pattern2 pattern3
+ | Ast.DOTS(l) -> pattern3
+ | _ -> failwith "circles and stars not supported")
+ else pattern_as_given
+ | Ast.IfThen(ifheader,branch,aft) ->
+ ifthen ifheader branch aft after quantified minus_quantified
+ label llabel slabel statement make_match guard
+
+ | Ast.IfThenElse(ifheader,branch1,els,branch2,aft) ->
+ ifthenelse ifheader branch1 els branch2 aft after quantified
+ minus_quantified label llabel slabel statement make_match guard
+
+ | Ast.While(header,body,aft) | Ast.For(header,body,aft)
+ | Ast.Iterator(header,body,aft) ->
+ forwhile header body aft after quantified minus_quantified
+ label statement make_match guard
+
+ | Ast.Disj(stmt_dots_list) -> (* list shouldn't be empty *)
+ ctl_and
+ (label_pred_maker label)
+ (List.fold_left ctl_seqor CTL.False
+ (List.map
+ (function sl ->
+ statement_list sl after quantified minus_quantified label
+ llabel slabel true guard)
+ stmt_dots_list))
+
+ | Ast.Nest(stmt_dots,whencode,multi,bef,aft) ->
+ (* label in recursive call is None because label check is already
+ wrapped around the corresponding code *)
+
+ let bfvs =
+ match seq_fvs quantified [Ast.get_wcfvs whencode;Ast.get_fvs stmt_dots]
+ with
+ [(wcfvs,bothfvs);(bdfvs,_)] -> bothfvs
+ | _ -> failwith "not possible" in
+
+ (* no minus version because when code doesn't contain any minus code *)
+ let new_quantified = Common.union_set bfvs quantified in
+
+ quantify guard bfvs
+ (let dots_pattern =
+ statement_list stmt_dots (a2n after) new_quantified minus_quantified
+ None llabel slabel true guard in
+ dots_and_nests multi
+ (Some dots_pattern) whencode bef aft None after label
+ (process_bef_aft new_quantified minus_quantified
+ None llabel slabel true)
+ (function x ->
+ statement_list x Tail new_quantified minus_quantified None
+ llabel slabel true true)
+ (function x ->
+ statement x Tail new_quantified minus_quantified None
+ llabel slabel true)
+ guard (function x -> Ast.set_fvs [] (Ast.rewrap stmt x)))
+
+ | Ast.Dots((_,i,d,_),whencodes,bef,aft) ->
+ let dot_code =
+ match d with
+ Ast.MINUS(_,_) ->
+ (* no need for the fresh metavar, but ... is a bit wierd as a
+ variable name *)
+ Some(make_match (make_meta_rule_elem d ([],[],[])))
+ | _ -> None in
+ dots_and_nests false None whencodes bef aft dot_code after label
+ (process_bef_aft quantified minus_quantified None llabel slabel true)
+ (function x ->
+ statement_list x Tail quantified minus_quantified
+ None llabel slabel true true)
+ (function x ->
+ statement x Tail quantified minus_quantified None llabel slabel true)
+ guard (function x -> Ast.set_fvs [] (Ast.rewrap stmt x))
+
+ | Ast.Switch(header,lb,cases,rb) ->
+ let rec intersect_all = function
+ [] -> []
+ | [x] -> x
+ | x::xs -> intersect x (intersect_all xs) in
+ let rec union_all l = List.fold_left union [] l in
+ (* start normal variables *)
+ let header_fvs = Ast.get_fvs header in
+ let lb_fvs = Ast.get_fvs lb in
+ let case_fvs = List.map Ast.get_fvs cases in
+ let rb_fvs = Ast.get_fvs rb in
+ let (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) =
+ List.fold_left
+ (function (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) ->
+ function case_fvs ->
+ match seq_fvs quantified [header_fvs;lb_fvs;case_fvs;rb_fvs] with
+ [(efvs,b1fvs);(lbfvs,b2fvs);(casefvs,b3fvs);(rbfvs,_)] ->
+ (efvs::all_efvs,b1fvs::all_b1fvs,lbfvs::all_lbfvs,
+ b2fvs::all_b2fvs,casefvs::all_casefvs,b3fvs::all_b3fvs,
+ rbfvs::all_rbfvs)
+ | _ -> failwith "not possible")
+ ([],[],[],[],[],[],[]) case_fvs in
+ let (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) =
+ (List.rev all_efvs,List.rev all_b1fvs,List.rev all_lbfvs,
+ List.rev all_b2fvs,List.rev all_casefvs,List.rev all_b3fvs,
+ List.rev all_rbfvs) in
+ let exponlyfvs = intersect_all all_efvs in
+ let lbonlyfvs = intersect_all all_lbfvs in
+(* don't do anything with right brace. Hope there is no + code on it *)
+(* let rbonlyfvs = intersect_all all_rbfvs in*)
+ let b1fvs = union_all all_b1fvs in
+ let new1_quantified = union b1fvs quantified in
+ let b2fvs = union (union_all all_b1fvs) (intersect_all all_casefvs) in
+ let new2_quantified = union b2fvs new1_quantified in
+(* let b3fvs = union_all all_b3fvs in*)
+ (* ------------------- start minus free variables *)
+ let header_mfvs = Ast.get_mfvs header in
+ let lb_mfvs = Ast.get_mfvs lb in
+ let case_mfvs = List.map Ast.get_mfvs cases in
+ let rb_mfvs = Ast.get_mfvs rb in
+ let (all_mefvs,all_mb1fvs,all_mlbfvs,all_mb2fvs,
+ all_mcasefvs,all_mb3fvs,all_mrbfvs) =
+ List.fold_left
+ (function (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) ->
+ function case_mfvs ->
+ match
+ seq_fvs quantified
+ [header_mfvs;lb_mfvs;case_mfvs;rb_mfvs] with
+ [(efvs,b1fvs);(lbfvs,b2fvs);(casefvs,b3fvs);(rbfvs,_)] ->
+ (efvs::all_efvs,b1fvs::all_b1fvs,lbfvs::all_lbfvs,
+ b2fvs::all_b2fvs,casefvs::all_casefvs,b3fvs::all_b3fvs,
+ rbfvs::all_rbfvs)
+ | _ -> failwith "not possible")
+ ([],[],[],[],[],[],[]) case_mfvs in
+ let (all_mefvs,all_mb1fvs,all_mlbfvs,all_mb2fvs,
+ all_mcasefvs,all_mb3fvs,all_mrbfvs) =
+ (List.rev all_mefvs,List.rev all_mb1fvs,List.rev all_mlbfvs,
+ List.rev all_mb2fvs,List.rev all_mcasefvs,List.rev all_mb3fvs,
+ List.rev all_mrbfvs) in
+(* don't do anything with right brace. Hope there is no + code on it *)
+(* let rbonlyfvs = intersect_all all_rbfvs in*)
+ let mb1fvs = union_all all_mb1fvs in
+ let new1_mquantified = union mb1fvs quantified in
+ let mb2fvs = union (union_all all_mb1fvs) (intersect_all all_mcasefvs) in
+ let new2_mquantified = union mb2fvs new1_mquantified in
+(* let b3fvs = union_all all_b3fvs in*)
+ (* ------------------- end collection of free variables *)
+ let switch_header = quantify guard exponlyfvs (make_match header) in
+ let lb = quantify guard lbonlyfvs (make_match lb) in
+(* let rb = quantify guard rbonlyfvs (make_match rb) in*)
+ let case_headers =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let e1fvs =
+ match seq_fvs new2_quantified [Ast.get_fvs header] with
+ [(e1fvs,_)] -> e1fvs
+ | _ -> failwith "not possible" in
+ quantify guard e1fvs (real_make_match label true header)
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ let no_header =
+ ctl_not (List.fold_left ctl_or_fl CTL.False case_headers) in
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let case_code =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let (e1fvs,b1fvs,s1fvs) =
+ let fvs = [Ast.get_fvs header;Ast.get_fvs body] in
+ match seq_fvs new2_quantified fvs with
+ [(e1fvs,b1fvs);(s1fvs,_)] -> (e1fvs,b1fvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let (me1fvs,mb1fvs,ms1fvs) =
+ let fvs = [Ast.get_mfvs header;Ast.get_mfvs body] in
+ match seq_fvs new2_mquantified fvs with
+ [(e1fvs,b1fvs);(s1fvs,_)] -> (e1fvs,b1fvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let case_header =
+ quantify guard e1fvs (make_match header) in
+ let new3_quantified = union b1fvs new2_quantified in
+ let new3_mquantified = union mb1fvs new2_mquantified in
+ let body =
+ statement_list body Tail
+ new3_quantified new3_mquantified label llabel
+ (Some (lv,used)) true(*?*) guard in
+ quantify guard b1fvs (make_seq [case_header; body])
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ let default_required =
+ if List.exists
+ (function case ->
+ match Ast.unwrap case with
+ Ast.CaseLine(header,_) ->
+ (match Ast.unwrap header with
+ Ast.Default(_,_) -> true
+ | _ -> false)
+ | _ -> false)
+ cases
+ then function x -> x
+ else function x -> ctl_or (fallpred label) x in
+ let after_pred = aftpred label in
+ let body after_branch =
+ ctl_or
+ (default_required
+ (quantify guard b2fvs
+ (make_seq
+ [ctl_and lb
+ (List.fold_left ctl_and CTL.True
+ (List.map ctl_ex case_headers));
+ List.fold_left ctl_or_fl no_header case_code])))
+ after_branch in
+ let aft =
+ (rb_fvs,Ast.get_fresh rb,Ast.get_inherited rb,
+ match Ast.unwrap rb with
+ Ast.SeqEnd(rb) -> Ast.get_mcodekind rb
+ | _ -> failwith "not possible") in
+ let (switch_header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and switch_header label_pred,
+ (function body -> quantify true [lv] body))
+ else (switch_header,function x -> x) in
+ wrapper
+ (end_control_structure b1fvs switch_header body
+ after_pred (Some(ctl_ex after_pred)) None aft after label guard)
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ let (hfvs,b1fvs,lbfvs,b2fvs,b3fvs,b4fvs,rbfvs) =
+ match
+ seq_fvs quantified
+ [Ast.get_fvs header;Ast.get_fvs lbrace;Ast.get_fvs decls;
+ Ast.get_fvs body;Ast.get_fvs rbrace]
+ with
+ [(hfvs,b1fvs);(lbfvs,b2fvs);(_,b3fvs);(_,b4fvs);(rbfvs,_)] ->
+ (hfvs,b1fvs,lbfvs,b2fvs,b3fvs,b4fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let (mhfvs,mb1fvs,mlbfvs,mb2fvs,mb3fvs,mb4fvs,mrbfvs) =
+ match
+ seq_fvs quantified
+ [Ast.get_mfvs header;Ast.get_mfvs lbrace;Ast.get_mfvs decls;
+ Ast.get_mfvs body;Ast.get_mfvs rbrace]
+ with
+ [(hfvs,b1fvs);(lbfvs,b2fvs);(_,b3fvs);(_,b4fvs);(rbfvs,_)] ->
+ (hfvs,b1fvs,lbfvs,b2fvs,b3fvs,b4fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let function_header = quantify guard hfvs (make_match header) in
+ let start_brace = quantify guard lbfvs (make_match lbrace) in
+ let stripped_rbrace =
+ match Ast.unwrap rbrace with
+ Ast.SeqEnd((data,info,_,_)) ->
+ Ast.rewrap rbrace(Ast.SeqEnd (Ast.make_mcode data))
+ | _ -> failwith "unexpected close brace" in
+ let end_brace =
+ let exit = CTL.Pred (Lib_engine.Exit,CTL.Control) in
+ let errorexit = CTL.Pred (Lib_engine.ErrorExit,CTL.Control) in
+ let fake_brace = CTL.Pred (Lib_engine.FakeBrace,CTL.Control) in
+ ctl_and
+ (quantify guard rbfvs (make_match rbrace))
+ (ctl_and
+ (* the following finds the beginning of the fake braces,
+ if there are any, not completely sure how this works.
+ sse the examples sw and return *)
+ (ctl_back_ex (ctl_not fake_brace))
+ (ctl_au (make_match stripped_rbrace) (ctl_or exit errorexit))) in
+ let new_quantified3 =
+ Common.union_set b1fvs
+ (Common.union_set b2fvs (Common.union_set b3fvs quantified)) in
+ let new_quantified4 = Common.union_set b4fvs new_quantified3 in
+ let new_mquantified3 =
+ Common.union_set mb1fvs
+ (Common.union_set mb2fvs
+ (Common.union_set mb3fvs minus_quantified)) in
+ let new_mquantified4 = Common.union_set mb4fvs new_mquantified3 in
+ let fn_nest =
+ match (Ast.undots decls,Ast.undots body,contains_modif rbrace) with
+ ([],[body],false) ->
+ (match Ast.unwrap body with
+ Ast.Nest(stmt_dots,[],multi,_,_) ->
+ if multi
+ then None (* not sure how to optimize this case *)
+ else Some (Common.Left stmt_dots)
+ | Ast.Dots(_,whencode,_,_) -> Some (Common.Right whencode)
+ | _ -> None)
+ | _ -> None in
+ let body_code =
+ match fn_nest with
+ Some (Common.Left stmt_dots) ->
+ (* special case for function header + body - header is unambiguous
+ and unique, so we can just look for the nested body anywhere
+ else in the CFG *)
+ CTL.AndAny
+ (CTL.FORWARD,guard_to_strict guard,start_brace,
+ statement_list stmt_dots
+ (* discards match on right brace, but don't need it *)
+ (Guard (make_seq_after end_brace after))
+ new_quantified4 new_mquantified4
+ None llabel slabel true guard)
+ | Some (Common.Right whencode) ->
+ (* try to be more efficient for the case where the body is just
+ ... Perhaps this is too much of a special case, but useful
+ for dropping a parameter and checking that it is never used. *)
+ make_seq
+ [start_brace;
+ match whencode with
+ [] -> CTL.True
+ | _ ->
+ let leftarg =
+ ctl_and
+ (ctl_not
+ (List.fold_left
+ (function prev ->
+ function
+ Ast.WhenAlways(s) -> prev
+ | Ast.WhenNot(sl) ->
+ let x =
+ statement_list sl Tail
+ new_quantified4 new_mquantified4
+ label llabel slabel true true in
+ ctl_or prev x
+ | Ast.WhenModifier(Ast.WhenAny) -> CTL.False
+ | Ast.WhenModifier(_) -> prev)
+ CTL.False whencode))
+ (List.fold_left
+ (function prev ->
+ function
+ Ast.WhenAlways(s) ->
+ let x =
+ statement s Tail
+ new_quantified4 new_mquantified4
+ label llabel slabel true in
+ ctl_and prev x
+ | Ast.WhenNot(sl) -> prev
+ | Ast.WhenModifier(Ast.WhenAny) -> CTL.True
+ | Ast.WhenModifier(_) -> prev)
+ CTL.True whencode) in
+ ctl_au leftarg (make_match stripped_rbrace)]
+ | None ->
+ make_seq
+ [start_brace;
+ quantify guard b3fvs
+ (statement_list decls
+ (After
+ (quantify guard b4fvs
+ (statement_list body
+ (After (make_seq_after end_brace after))
+ new_quantified4 new_mquantified4
+ None llabel slabel true guard)))
+ new_quantified3 new_mquantified3 None llabel slabel
+ false guard)] in
+ quantify guard b1fvs
+ (make_seq [function_header; quantify guard b2fvs body_code])
+ | Ast.Define(header,body) ->
+ let (hfvs,bfvs,bodyfvs) =
+ match seq_fvs quantified [Ast.get_fvs header;Ast.get_fvs body]
+ with
+ [(hfvs,b1fvs);(bodyfvs,_)] -> (hfvs,b1fvs,bodyfvs)
+ | _ -> failwith "not possible" in
+ let (mhfvs,mbfvs,mbodyfvs) =
+ match seq_fvs minus_quantified [Ast.get_mfvs header;Ast.get_mfvs body]
+ with
+ [(hfvs,b1fvs);(bodyfvs,_)] -> (hfvs,b1fvs,bodyfvs)
+ | _ -> failwith "not possible" in
+ let define_header = quantify guard hfvs (make_match header) in
+ let body_code =
+ statement_list body after
+ (Common.union_set bfvs quantified)
+ (Common.union_set mbfvs minus_quantified)
+ None llabel slabel true guard in
+ quantify guard bfvs (make_seq [define_header; body_code])
+ | Ast.OptStm(stm) ->
+ failwith "OptStm should have been compiled away\n"
+ | Ast.UniqueStm(stm) -> failwith "arities not yet supported"
+ | _ -> failwith "not supported" in
+ if guard or !dots_done
+ then term
+ else
+ do_between_dots stmt term after quantified minus_quantified
+ label llabel slabel guard
+
+(* term is the translation of stmt *)
+and do_between_dots stmt term after quantified minus_quantified
+ label llabel slabel guard =
+ match Ast.get_dots_bef_aft stmt with
+ Ast.AddingBetweenDots (brace_term,n)
+ | Ast.DroppingBetweenDots (brace_term,n) ->
+ let match_brace =
+ statement brace_term after quantified minus_quantified
+ label llabel slabel guard in
+ let v = Printf.sprintf "_r_%d" n in
+ let case1 = ctl_and CTL.NONSTRICT (CTL.Ref v) match_brace in
+ let case2 = ctl_and CTL.NONSTRICT (ctl_not (CTL.Ref v)) term in
+ CTL.Let
+ (v,ctl_or
+ (ctl_back_ex (ctl_or (truepred label) (inlooppred label)))
+ (ctl_back_ex (ctl_back_ex (falsepred label))),
+ ctl_or case1 case2)
+ | Ast.NoDots -> term
+
+(* un_process_bef_aft is because we don't want to do transformation in this
+ code, and thus don't case about braces before or after it *)
+and process_bef_aft quantified minus_quantified label llabel slabel guard =
+ function
+ Ast.WParen (re,n) ->
+ let paren_pred = CTL.Pred (Lib_engine.Paren n,CTL.Control) in
+ let s = guard_to_strict guard in
+ quantify true (get_unquantified quantified [n])
+ (ctl_and s (make_raw_match None guard re) paren_pred)
+ | Ast.Other s ->
+ statement s Tail quantified minus_quantified label llabel slabel guard
+ | Ast.Other_dots d ->
+ statement_list d Tail quantified minus_quantified
+ label llabel slabel true guard
+
+(* --------------------------------------------------------------------- *)
+(* cleanup: convert AX to EX for pdots.
+Concretely: AX(A[...] & E[...]) becomes AX(A[...]) & EX(E[...])
+This is what we wanted in the first place, but it wasn't possible to make
+because the AX and its argument are not created in the same place.
+Rather clunky... *)
+(* also cleanup XX, which is a marker for the case where the programmer
+specifies to change the quantifier on .... Assumed to only occur after one AX
+or EX, or at top level. *)
+
+let rec cleanup c =
+ let c = match c with CTL.XX(c) -> c | _ -> c in
+ match c with
+ CTL.False -> CTL.False
+ | CTL.True -> CTL.True
+ | CTL.Pred(p) -> CTL.Pred(p)
+ | CTL.Not(phi) -> CTL.Not(cleanup phi)
+ | CTL.Exists(keep,v,phi) -> CTL.Exists(keep,v,cleanup phi)
+ | CTL.AndAny(dir,s,phi1,phi2) ->
+ CTL.AndAny(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.HackForStmt(dir,s,phi1,phi2) ->
+ CTL.HackForStmt(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.And(s,phi1,phi2) -> CTL.And(s,cleanup phi1,cleanup phi2)
+ | CTL.Or(phi1,phi2) -> CTL.Or(cleanup phi1,cleanup phi2)
+ | CTL.SeqOr(phi1,phi2) -> CTL.SeqOr(cleanup phi1,cleanup phi2)
+ | CTL.Implies(phi1,phi2) -> CTL.Implies(cleanup phi1,cleanup phi2)
+ | CTL.AF(dir,s,phi1) -> CTL.AF(dir,s,cleanup phi1)
+ | CTL.AX(CTL.FORWARD,s,
+ CTL.Let(v1,e1,
+ CTL.And(CTL.NONSTRICT,CTL.AU(CTL.FORWARD,s2,e2,e3),
+ CTL.EU(CTL.FORWARD,e4,e5)))) ->
+ CTL.Let(v1,e1,
+ CTL.And(CTL.NONSTRICT,
+ CTL.AX(CTL.FORWARD,s,CTL.AU(CTL.FORWARD,s2,e2,e3)),
+ CTL.EX(CTL.FORWARD,CTL.EU(CTL.FORWARD,e4,e5))))
+ | CTL.AX(dir,s,CTL.XX(phi)) -> CTL.EX(dir,CTL.XX(cleanup phi))
+ | CTL.EX(dir,CTL.XX((CTL.AU(_,s,_,_)) as phi)) ->
+ CTL.AX(dir,s,CTL.XX(cleanup phi))
+ | CTL.XX(phi) -> failwith "bad XX"
+ | CTL.AX(dir,s,phi1) -> CTL.AX(dir,s,cleanup phi1)
+ | CTL.AG(dir,s,phi1) -> CTL.AG(dir,s,cleanup phi1)
+ | CTL.EF(dir,phi1) -> CTL.EF(dir,cleanup phi1)
+ | CTL.EX(dir,phi1) -> CTL.EX(dir,cleanup phi1)
+ | CTL.EG(dir,phi1) -> CTL.EG(dir,cleanup phi1)
+ | CTL.AW(dir,s,phi1,phi2) -> CTL.AW(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.AU(dir,s,phi1,phi2) -> CTL.AU(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.EU(dir,phi1,phi2) -> CTL.EU(dir,cleanup phi1,cleanup phi2)
+ | CTL.Let (x,phi1,phi2) -> CTL.Let (x,cleanup phi1,cleanup phi2)
+ | CTL.LetR (dir,x,phi1,phi2) -> CTL.LetR (dir,x,cleanup phi1,cleanup phi2)
+ | CTL.Ref(s) -> CTL.Ref(s)
+ | CTL.Uncheck(phi1) -> CTL.Uncheck(cleanup phi1)
+ | CTL.InnerAnd(phi1) -> CTL.InnerAnd(cleanup phi1)
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+
+let top_level name (ua,pos) t =
+ let ua = List.filter (function (nm,_) -> nm = name) ua in
+ used_after := ua;
+ saved := Ast.get_saved t;
+ let quantified = Common.minus_set ua pos in
+ quantify false quantified
+ (match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) -> failwith "not supported fileinfo"
+ | Ast.DECL(stmt) ->
+ let unopt = elim_opt.V.rebuilder_statement stmt in
+ let unopt = preprocess_dots_e unopt in
+ cleanup(statement unopt VeryEnd quantified [] None None None false)
+ | Ast.CODE(stmt_dots) ->
+ let unopt = elim_opt.V.rebuilder_statement_dots stmt_dots in
+ let unopt = preprocess_dots unopt in
+ let starts_with_dots =
+ match Ast.undots stmt_dots with
+ d::ds ->
+ (match Ast.unwrap d with
+ Ast.Dots(_,_,_,_) | Ast.Circles(_,_,_,_)
+ | Ast.Stars(_,_,_,_) -> true
+ | _ -> false)
+ | _ -> false in
+ let starts_with_brace =
+ match Ast.undots stmt_dots with
+ d::ds ->
+ (match Ast.unwrap d with
+ Ast.Seq(_) -> true
+ | _ -> false)
+ | _ -> false in
+ let res =
+ statement_list unopt VeryEnd quantified [] None None None
+ false false in
+ cleanup
+ (if starts_with_dots
+ then
+ (* EX because there is a loop on enter/top *)
+ ctl_and CTL.NONSTRICT (toppred None) (ctl_ex res)
+ else if starts_with_brace
+ then
+ ctl_and CTL.NONSTRICT
+ (ctl_not(CTL.EX(CTL.BACKWARD,(funpred None)))) res
+ else res)
+ | Ast.ERRORWORDS(exps) -> failwith "not supported errorwords")
+
+(* --------------------------------------------------------------------- *)
+(* Entry points *)
+
+let asttoctlz (name,(_,_,exists_flag),l) used_after positions =
+ letctr := 0;
+ labelctr := 0;
+ (match exists_flag with
+ Ast.Exists -> exists := Exists
+ | Ast.Forall -> exists := Forall
+ | Ast.ReverseForall -> exists := ReverseForall
+ | Ast.Undetermined ->
+ exists := if !Flag.sgrep_mode2 then Exists else Forall);
+
+ let (l,used_after) =
+ List.split
+ (List.filter
+ (function (t,_) ->
+ match Ast.unwrap t with Ast.ERRORWORDS(exps) -> false | _ -> true)
+ (List.combine l (List.combine used_after positions))) in
+ let res = List.map2 (top_level name) used_after l in
+ exists := Forall;
+ res
+
+let asttoctl r used_after positions =
+ match r with
+ Ast.ScriptRule _ -> []
+ | Ast.CocciRule (a,b,c,_) -> asttoctlz (a,b,c) used_after positions
+
+let pp_cocci_predicate (pred,modif) =
+ Pretty_print_engine.pp_predicate pred
+
+let cocci_predicate_to_string (pred,modif) =
+ Pretty_print_engine.predicate_to_string pred
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* for MINUS and CONTEXT, pos is always None in this file *)
+(*search for require*)
+(* true = don't see all matched nodes, only modified ones *)
+let onlyModif = ref true(*false*)
+
+type ex = Exists | Forall | ReverseForall
+let exists = ref Forall
+
+module Ast = Ast_cocci
+module V = Visitor_ast
+module CTL = Ast_ctl
+
+let warning s = Printf.fprintf stderr "warning: %s\n" s
+
+type cocci_predicate = Lib_engine.predicate * Ast.meta_name Ast_ctl.modif
+type formula =
+ (cocci_predicate,Ast.meta_name, Wrapper_ctl.info) Ast_ctl.generic_ctl
+
+let union = Common.union_set
+let intersect l1 l2 = List.filter (function x -> List.mem x l2) l1
+let subset l1 l2 = List.for_all (function x -> List.mem x l2) l1
+
+let foldl1 f xs = List.fold_left f (List.hd xs) (List.tl xs)
+let foldr1 f xs =
+ let xs = List.rev xs in List.fold_left f (List.hd xs) (List.tl xs)
+
+let used_after = ref ([] : Ast.meta_name list)
+let guard_to_strict guard = if guard then CTL.NONSTRICT else CTL.STRICT
+
+let saved = ref ([] : Ast.meta_name list)
+
+let string2var x = ("",x)
+
+(* --------------------------------------------------------------------- *)
+(* predicates matching various nodes in the graph *)
+
+let ctl_and s x y =
+ match (x,y) with
+ (CTL.False,_) | (_,CTL.False) -> CTL.False
+ | (CTL.True,a) | (a,CTL.True) -> a
+ | _ -> CTL.And(s,x,y)
+
+let ctl_or x y =
+ match (x,y) with
+ (CTL.True,_) | (_,CTL.True) -> CTL.True
+ | (CTL.False,a) | (a,CTL.False) -> a
+ | _ -> CTL.Or(x,y)
+
+let ctl_or_fl x y =
+ match (x,y) with
+ (CTL.True,_) | (_,CTL.True) -> CTL.True
+ | (CTL.False,a) | (a,CTL.False) -> a
+ | _ -> CTL.Or(y,x)
+
+let ctl_seqor x y =
+ match (x,y) with
+ (CTL.True,_) | (_,CTL.True) -> CTL.True
+ | (CTL.False,a) | (a,CTL.False) -> a
+ | _ -> CTL.SeqOr(x,y)
+
+let ctl_not = function
+ CTL.True -> CTL.False
+ | CTL.False -> CTL.True
+ | x -> CTL.Not(x)
+
+let ctl_ax s = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x ->
+ match !exists with
+ Exists -> CTL.EX(CTL.FORWARD,x)
+ | Forall -> CTL.AX(CTL.FORWARD,s,x)
+ | ReverseForall -> failwith "not supported"
+
+let ctl_ax_absolute s = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.AX(CTL.FORWARD,s,x)
+
+let ctl_ex = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.EX(CTL.FORWARD,x)
+
+(* This stays being AX even for sgrep_mode, because it is used to identify
+the structure of the term, not matching the pattern. *)
+let ctl_back_ax = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.AX(CTL.BACKWARD,CTL.NONSTRICT,x)
+
+let ctl_back_ex = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.EX(CTL.BACKWARD,x)
+
+let ctl_ef = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.EF(CTL.FORWARD,x)
+
+let ctl_ag s = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.AG(CTL.FORWARD,s,x)
+
+let ctl_au s x y =
+ match (x,!exists) with
+ (CTL.True,Exists) -> CTL.EF(CTL.FORWARD,y)
+ | (CTL.True,Forall) -> CTL.AF(CTL.FORWARD,s,y)
+ | (CTL.True,ReverseForall) -> failwith "not supported"
+ | (_,Exists) -> CTL.EU(CTL.FORWARD,x,y)
+ | (_,Forall) -> CTL.AU(CTL.FORWARD,s,x,y)
+ | (_,ReverseForall) -> failwith "not supported"
+
+let ctl_anti_au s x y = (* only for ..., where the quantifier is changed *)
+ CTL.XX
+ (match (x,!exists) with
+ (CTL.True,Exists) -> CTL.AF(CTL.FORWARD,s,y)
+ | (CTL.True,Forall) -> CTL.EF(CTL.FORWARD,y)
+ | (CTL.True,ReverseForall) -> failwith "not supported"
+ | (_,Exists) -> CTL.AU(CTL.FORWARD,s,x,y)
+ | (_,Forall) -> CTL.EU(CTL.FORWARD,x,y)
+ | (_,ReverseForall) -> failwith "not supported")
+
+let ctl_uncheck = function
+ CTL.True -> CTL.True
+ | CTL.False -> CTL.False
+ | x -> CTL.Uncheck x
+
+let label_pred_maker = function
+ None -> CTL.True
+ | Some (label_var,used) ->
+ used := true;
+ CTL.Pred(Lib_engine.PrefixLabel(label_var),CTL.Control)
+
+let bclabel_pred_maker = function
+ None -> CTL.True
+ | Some (label_var,used) ->
+ used := true;
+ CTL.Pred(Lib_engine.BCLabel(label_var),CTL.Control)
+
+let predmaker guard pred label =
+ ctl_and (guard_to_strict guard) (CTL.Pred pred) (label_pred_maker label)
+
+let aftpred = predmaker false (Lib_engine.After, CTL.Control)
+let retpred = predmaker false (Lib_engine.Return, CTL.Control)
+let funpred = predmaker false (Lib_engine.FunHeader, CTL.Control)
+let toppred = predmaker false (Lib_engine.Top, CTL.Control)
+let exitpred = predmaker false (Lib_engine.ErrorExit, CTL.Control)
+let endpred = predmaker false (Lib_engine.Exit, CTL.Control)
+let gotopred = predmaker false (Lib_engine.Goto, CTL.Control)
+let inlooppred = predmaker false (Lib_engine.InLoop, CTL.Control)
+let truepred = predmaker false (Lib_engine.TrueBranch, CTL.Control)
+let falsepred = predmaker false (Lib_engine.FalseBranch, CTL.Control)
+let fallpred = predmaker false (Lib_engine.FallThrough, CTL.Control)
+
+let aftret label_var f = ctl_or (aftpred label_var) (exitpred label_var)
+
+let letctr = ref 0
+let get_let_ctr _ =
+ let cur = !letctr in
+ letctr := cur + 1;
+ Printf.sprintf "r%d" cur
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Eliminate OptStm *)
+
+(* for optional thing with nothing after, should check that the optional thing
+never occurs. otherwise the matching stops before it occurs *)
+let elim_opt =
+ let mcode x = x in
+ let donothing r k e = k e in
+
+ let fvlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_fvs l) in
+
+ let mfvlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_mfvs l) in
+
+ let freshlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_fresh l) in
+
+ let inheritedlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_inherited l) in
+
+ let savedlist l =
+ List.fold_left Common.union_set [] (List.map Ast.get_saved l) in
+
+ let varlists l =
+ (fvlist l, mfvlist l, freshlist l, inheritedlist l, savedlist l) in
+
+ let rec dots_list unwrapped wrapped =
+ match (unwrapped,wrapped) with
+ ([],_) -> []
+
+ | (Ast.Dots(_,_,_,_)::Ast.OptStm(stm)::(Ast.Dots(_,_,_,_) as u)::urest,
+ d0::s::d1::rest)
+ | (Ast.Nest(_,_,_,_,_)::Ast.OptStm(stm)::(Ast.Dots(_,_,_,_) as u)::urest,
+ d0::s::d1::rest) ->
+ let l = Ast.get_line stm in
+ let new_rest1 = stm :: (dots_list (u::urest) (d1::rest)) in
+ let new_rest2 = dots_list urest rest in
+ let (fv_rest1,mfv_rest1,fresh_rest1,inherited_rest1,s1) =
+ varlists new_rest1 in
+ let (fv_rest2,mfv_rest2,fresh_rest2,inherited_rest2,s2) =
+ varlists new_rest2 in
+ [d0;
+ {(Ast.make_term
+ (Ast.Disj
+ [{(Ast.make_term(Ast.DOTS(new_rest1))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest1;
+ Ast.minus_free_vars = mfv_rest1;
+ Ast.fresh_vars = fresh_rest1;
+ Ast.inherited = inherited_rest1;
+ Ast.saved_witness = s1};
+ {(Ast.make_term(Ast.DOTS(new_rest2))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest2;
+ Ast.minus_free_vars = mfv_rest2;
+ Ast.fresh_vars = fresh_rest2;
+ Ast.inherited = inherited_rest2;
+ Ast.saved_witness = s2}])) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest1;
+ Ast.minus_free_vars = mfv_rest1;
+ Ast.fresh_vars = fresh_rest1;
+ Ast.inherited = inherited_rest1;
+ Ast.saved_witness = s1}]
+
+ | (Ast.OptStm(stm)::urest,_::rest) ->
+ let l = Ast.get_line stm in
+ let new_rest1 = dots_list urest rest in
+ let new_rest2 = stm::new_rest1 in
+ let (fv_rest1,mfv_rest1,fresh_rest1,inherited_rest1,s1) =
+ varlists new_rest1 in
+ let (fv_rest2,mfv_rest2,fresh_rest2,inherited_rest2,s2) =
+ varlists new_rest2 in
+ [{(Ast.make_term
+ (Ast.Disj
+ [{(Ast.make_term(Ast.DOTS(new_rest2))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest2;
+ Ast.minus_free_vars = mfv_rest2;
+ Ast.fresh_vars = fresh_rest2;
+ Ast.inherited = inherited_rest2;
+ Ast.saved_witness = s2};
+ {(Ast.make_term(Ast.DOTS(new_rest1))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest1;
+ Ast.minus_free_vars = mfv_rest1;
+ Ast.fresh_vars = fresh_rest1;
+ Ast.inherited = inherited_rest1;
+ Ast.saved_witness = s1}])) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_rest2;
+ Ast.minus_free_vars = mfv_rest2;
+ Ast.fresh_vars = fresh_rest2;
+ Ast.inherited = inherited_rest2;
+ Ast.saved_witness = s2}]
+
+ | ([Ast.Dots(_,_,_,_);Ast.OptStm(stm)],[d1;_]) ->
+ let l = Ast.get_line stm in
+ let fv_stm = Ast.get_fvs stm in
+ let mfv_stm = Ast.get_mfvs stm in
+ let fresh_stm = Ast.get_fresh stm in
+ let inh_stm = Ast.get_inherited stm in
+ let saved_stm = Ast.get_saved stm in
+ let fv_d1 = Ast.get_fvs d1 in
+ let mfv_d1 = Ast.get_mfvs d1 in
+ let fresh_d1 = Ast.get_fresh d1 in
+ let inh_d1 = Ast.get_inherited d1 in
+ let saved_d1 = Ast.get_saved d1 in
+ let fv_both = Common.union_set fv_stm fv_d1 in
+ let mfv_both = Common.union_set mfv_stm mfv_d1 in
+ let fresh_both = Common.union_set fresh_stm fresh_d1 in
+ let inh_both = Common.union_set inh_stm inh_d1 in
+ let saved_both = Common.union_set saved_stm saved_d1 in
+ [d1;
+ {(Ast.make_term
+ (Ast.Disj
+ [{(Ast.make_term(Ast.DOTS([stm]))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_stm;
+ Ast.minus_free_vars = mfv_stm;
+ Ast.fresh_vars = fresh_stm;
+ Ast.inherited = inh_stm;
+ Ast.saved_witness = saved_stm};
+ {(Ast.make_term(Ast.DOTS([d1]))) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_d1;
+ Ast.minus_free_vars = mfv_d1;
+ Ast.fresh_vars = fresh_d1;
+ Ast.inherited = inh_d1;
+ Ast.saved_witness = saved_d1}])) with
+ Ast.node_line = l;
+ Ast.free_vars = fv_both;
+ Ast.minus_free_vars = mfv_both;
+ Ast.fresh_vars = fresh_both;
+ Ast.inherited = inh_both;
+ Ast.saved_witness = saved_both}]
+
+ | ([Ast.Nest(_,_,_,_,_);Ast.OptStm(stm)],[d1;_]) ->
+ let l = Ast.get_line stm in
+ let rw = Ast.rewrap stm in
+ let rwd = Ast.rewrap stm in
+ let dots = Ast.Dots(Ast.make_mcode "...",[],[],[]) in
+ [d1;rw(Ast.Disj
+ [rwd(Ast.DOTS([stm]));
+ {(Ast.make_term(Ast.DOTS([rw dots])))
+ with Ast.node_line = l}])]
+
+ | (_::urest,stm::rest) -> stm :: (dots_list urest rest)
+ | _ -> failwith "not possible" in
+
+ let stmtdotsfn r k d =
+ let d = k d in
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(dots_list (List.map Ast.unwrap l) l)
+ | Ast.CIRCLES(l) -> failwith "elimopt: not supported"
+ | Ast.STARS(l) -> failwith "elimopt: not supported") in
+
+ V.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing stmtdotsfn donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* after management *)
+(* We need Guard for the following case:
+<...
+ a
+ <...
+ b
+ ...>
+...>
+foo();
+
+Here the inner <... b ...> should not go past foo. But foo is not the
+"after" of the body of the outer nest, because we don't want to search for
+it in the case where the body of the outer nest ends in something other
+than dots or a nest. *)
+
+(* what is the difference between tail and end??? *)
+
+type after = After of formula | Guard of formula | Tail | End | VeryEnd
+
+let a2n = function After x -> Guard x | a -> a
+
+let print_ctl x =
+ let pp_pred (x,_) = Pretty_print_engine.pp_predicate x in
+ let pp_meta (_,x) = Common.pp x in
+ Pretty_print_ctl.pp_ctl (pp_pred,pp_meta) false x;
+ Format.print_newline()
+
+let print_after = function
+ After ctl -> Printf.printf "After:\n"; print_ctl ctl
+ | Guard ctl -> Printf.printf "Guard:\n"; print_ctl ctl
+ | Tail -> Printf.printf "Tail\n"
+ | VeryEnd -> Printf.printf "Very End\n"
+ | End -> Printf.printf "End\n"
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+let fresh_var _ = string2var "_v"
+let fresh_pos _ = string2var "_pos" (* must be a constant *)
+
+let fresh_metavar _ = "_S"
+
+(* fvinfo is going to end up being from the whole associated statement.
+ it would be better if it were just the free variables in d, but free_vars.ml
+ doesn't keep track of free variables on + code *)
+let make_meta_rule_elem d fvinfo =
+ let nm = fresh_metavar() in
+ Ast.make_meta_rule_elem nm d fvinfo
+
+let get_unquantified quantified vars =
+ List.filter (function x -> not (List.mem x quantified)) vars
+
+let make_seq guard l =
+ let s = guard_to_strict guard in
+ foldr1 (function rest -> function cur -> ctl_and s cur (ctl_ax s rest)) l
+
+let make_seq_after2 guard first rest =
+ let s = guard_to_strict guard in
+ match rest with
+ After rest -> ctl_and s first (ctl_ax s (ctl_ax s rest))
+ | _ -> first
+
+let make_seq_after guard first rest =
+ match rest with
+ After rest -> make_seq guard [first;rest]
+ | _ -> first
+
+let opt_and guard first rest =
+ let s = guard_to_strict guard in
+ match first with
+ None -> rest
+ | Some first -> ctl_and s first rest
+
+let and_after guard first rest =
+ let s = guard_to_strict guard in
+ match rest with After rest -> ctl_and s first rest | _ -> first
+
+let contains_modif =
+ let bind x y = x or y in
+ let option_default = false in
+ let mcode r (_,_,kind,_) =
+ match kind with
+ Ast.MINUS(_,_) -> true
+ | Ast.PLUS -> failwith "not possible"
+ | Ast.CONTEXT(_,info) -> not (info = Ast.NOTHING) in
+ let do_nothing r k e = k e in
+ let rule_elem r k re =
+ let res = k re in
+ match Ast.unwrap re with
+ Ast.FunHeader(bef,_,fninfo,name,lp,params,rp) ->
+ bind (mcode r ((),(),bef,Ast.NoMetaPos)) res
+ | Ast.Decl(bef,_,decl) -> bind (mcode r ((),(),bef,Ast.NoMetaPos)) res
+ | _ -> res in
+ let recursor =
+ V.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing rule_elem do_nothing do_nothing do_nothing do_nothing in
+ recursor.V.combiner_rule_elem
+
+(* code is not a DisjRuleElem *)
+let make_match label guard code =
+ let v = fresh_var() in
+ let matcher = Lib_engine.Match(code) in
+ if contains_modif code && not guard
+ then CTL.Exists(true,v,predmaker guard (matcher,CTL.Modif v) label)
+ else
+ let iso_info = !Flag.track_iso_usage && not (Ast.get_isos code = []) in
+ (match (iso_info,!onlyModif,guard,
+ intersect !used_after (Ast.get_fvs code)) with
+ (false,true,_,[]) | (_,_,true,_) ->
+ predmaker guard (matcher,CTL.Control) label
+ | _ -> CTL.Exists(true,v,predmaker guard (matcher,CTL.UnModif v) label))
+
+let make_raw_match label guard code =
+ predmaker guard (Lib_engine.Match(code),CTL.Control) label
+
+let rec seq_fvs quantified = function
+ [] -> []
+ | fv1::fvs ->
+ let t1fvs = get_unquantified quantified fv1 in
+ let termfvs =
+ List.fold_left Common.union_set []
+ (List.map (get_unquantified quantified) fvs) in
+ let bothfvs = Common.inter_set t1fvs termfvs in
+ let t1onlyfvs = Common.minus_set t1fvs bothfvs in
+ let new_quantified = Common.union_set bothfvs quantified in
+ (t1onlyfvs,bothfvs)::(seq_fvs new_quantified fvs)
+
+let quantify guard =
+ List.fold_right
+ (function cur ->
+ function code -> CTL.Exists (not guard && List.mem cur !saved,cur,code))
+
+let non_saved_quantify =
+ List.fold_right
+ (function cur -> function code -> CTL.Exists (false,cur,code))
+
+let intersectll lst nested_list =
+ List.filter (function x -> List.exists (List.mem x) nested_list) lst
+
+(* --------------------------------------------------------------------- *)
+(* Count depth of braces. The translation of a closed brace appears deeply
+nested within the translation of the sequence term, so the name of the
+paren var has to take into account the names of the nested braces. On the
+other hand the close brace does not escape, so we don't have to take into
+account other paren variable names. *)
+
+(* called repetitively, which is inefficient, but less trouble than adding a
+new field to Seq and FunDecl *)
+let count_nested_braces s =
+ let bind x y = max x y in
+ let option_default = 0 in
+ let stmt_count r k s =
+ match Ast.unwrap s with
+ Ast.Seq(_,_,_,_) | Ast.FunDecl(_,_,_,_,_) -> (k s) + 1
+ | _ -> k s in
+ let donothing r k e = k e in
+ let mcode r x = 0 in
+ let recursor = V.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing stmt_count donothing donothing donothing in
+ let res = string_of_int (recursor.V.combiner_statement s) in
+ string2var ("p"^res)
+
+let labelctr = ref 0
+let get_label_ctr _ =
+ let cur = !labelctr in
+ labelctr := cur + 1;
+ string2var (Printf.sprintf "l%d" cur)
+
+(* --------------------------------------------------------------------- *)
+(* annotate dots with before and after neighbors *)
+
+let print_bef_aft = function
+ Ast.WParen (re,n) ->
+ Printf.printf "bef/aft\n";
+ Pretty_print_cocci.rule_elem "" re;
+ Format.print_newline()
+ | Ast.Other s ->
+ Printf.printf "bef/aft\n";
+ Pretty_print_cocci.statement "" s;
+ Format.print_newline()
+ | Ast.Other_dots d ->
+ Printf.printf "bef/aft\n";
+ Pretty_print_cocci.statement_dots d;
+ Format.print_newline()
+
+(* [] can only occur if we are in a disj, where it comes from a ? In that
+case, we want to use a, which accumulates all of the previous patterns in
+their entirety. *)
+let rec get_before_elem sl a =
+ match Ast.unwrap sl with
+ Ast.DOTS(x) ->
+ let rec loop sl a =
+ match sl with
+ [] -> ([],Common.Right a)
+ | [e] ->
+ let (e,ea) = get_before_e e a in
+ ([e],Common.Left ea)
+ | e::sl ->
+ let (e,ea) = get_before_e e a in
+ let (sl,sla) = loop sl ea in
+ (e::sl,sla) in
+ let (l,a) = loop x a in
+ (Ast.rewrap sl (Ast.DOTS(l)),a)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+and get_before sl a =
+ match get_before_elem sl a with
+ (term,Common.Left x) -> (term,x)
+ | (term,Common.Right x) -> (term,x)
+
+and get_before_whencode wc =
+ List.map
+ (function
+ Ast.WhenNot w -> let (w,_) = get_before w [] in Ast.WhenNot w
+ | Ast.WhenAlways w -> let (w,_) = get_before_e w [] in Ast.WhenAlways w
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x)
+ | Ast.WhenNotTrue w -> Ast.WhenNotTrue w
+ | Ast.WhenNotFalse w -> Ast.WhenNotFalse w)
+ wc
+
+and get_before_e s a =
+ match Ast.unwrap s with
+ Ast.Dots(d,w,_,aft) ->
+ (Ast.rewrap s (Ast.Dots(d,get_before_whencode w,a,aft)),a)
+ | Ast.Nest(stmt_dots,w,multi,_,aft) ->
+ let w = get_before_whencode w in
+ let (sd,_) = get_before stmt_dots a in
+ let a =
+ List.filter
+ (function
+ Ast.Other a ->
+ let unifies =
+ Unify_ast.unify_statement_dots
+ (Ast.rewrap s (Ast.DOTS([a]))) stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | Ast.Other_dots a ->
+ let unifies = Unify_ast.unify_statement_dots a stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | _ -> true)
+ a in
+ (Ast.rewrap s (Ast.Nest(sd,w,multi,a,aft)),[Ast.Other_dots stmt_dots])
+ | Ast.Disj(stmt_dots_list) ->
+ let (dsl,dsla) =
+ List.split (List.map (function e -> get_before e a) stmt_dots_list) in
+ (Ast.rewrap s (Ast.Disj(dsl)),List.fold_left Common.union_set [] dsla)
+ | Ast.Atomic(ast) ->
+ (match Ast.unwrap ast with
+ Ast.MetaStmt(_,_,_,_) -> (s,[])
+ | _ -> (s,[Ast.Other s]))
+ | Ast.Seq(lbrace,decls,body,rbrace) ->
+ let index = count_nested_braces s in
+ let (de,dea) = get_before decls [Ast.WParen(lbrace,index)] in
+ let (bd,_) = get_before body dea in
+ (Ast.rewrap s (Ast.Seq(lbrace,de,bd,rbrace)),
+ [Ast.WParen(rbrace,index)])
+ | Ast.Define(header,body) ->
+ let (body,_) = get_before body [] in
+ (Ast.rewrap s (Ast.Define(header,body)), [Ast.Other s])
+ | Ast.IfThen(ifheader,branch,aft) ->
+ let (br,_) = get_before_e branch [] in
+ (Ast.rewrap s (Ast.IfThen(ifheader,br,aft)), [Ast.Other s])
+ | Ast.IfThenElse(ifheader,branch1,els,branch2,aft) ->
+ let (br1,_) = get_before_e branch1 [] in
+ let (br2,_) = get_before_e branch2 [] in
+ (Ast.rewrap s (Ast.IfThenElse(ifheader,br1,els,br2,aft)),[Ast.Other s])
+ | Ast.While(header,body,aft) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.While(header,bd,aft)),[Ast.Other s])
+ | Ast.For(header,body,aft) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.For(header,bd,aft)),[Ast.Other s])
+ | Ast.Do(header,body,tail) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.Do(header,bd,tail)),[Ast.Other s])
+ | Ast.Iterator(header,body,aft) ->
+ let (bd,_) = get_before_e body [] in
+ (Ast.rewrap s (Ast.Iterator(header,bd,aft)),[Ast.Other s])
+ | Ast.Switch(header,lb,cases,rb) ->
+ let cases =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let (body,_) = get_before body [] in
+ Ast.rewrap case_line (Ast.CaseLine(header,body))
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ (Ast.rewrap s (Ast.Switch(header,lb,cases,rb)),[Ast.Other s])
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ let (de,dea) = get_before decls [] in
+ let (bd,_) = get_before body dea in
+ (Ast.rewrap s (Ast.FunDecl(header,lbrace,de,bd,rbrace)),[])
+ | _ -> failwith "get_before_e: not supported"
+
+let rec get_after sl a =
+ match Ast.unwrap sl with
+ Ast.DOTS(x) ->
+ let rec loop sl =
+ match sl with
+ [] -> ([],a)
+ | e::sl ->
+ let (sl,sla) = loop sl in
+ let (e,ea) = get_after_e e sla in
+ (e::sl,ea) in
+ let (l,a) = loop x in
+ (Ast.rewrap sl (Ast.DOTS(l)),a)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+and get_after_whencode a wc =
+ List.map
+ (function
+ Ast.WhenNot w -> let (w,_) = get_after w a (*?*) in Ast.WhenNot w
+ | Ast.WhenAlways w -> let (w,_) = get_after_e w a in Ast.WhenAlways w
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x)
+ | Ast.WhenNotTrue w -> Ast.WhenNotTrue w
+ | Ast.WhenNotFalse w -> Ast.WhenNotFalse w)
+ wc
+
+and get_after_e s a =
+ match Ast.unwrap s with
+ Ast.Dots(d,w,bef,_) ->
+ (Ast.rewrap s (Ast.Dots(d,get_after_whencode a w,bef,a)),a)
+ | Ast.Nest(stmt_dots,w,multi,bef,_) ->
+ let w = get_after_whencode a w in
+ let (sd,_) = get_after stmt_dots a in
+ let a =
+ List.filter
+ (function
+ Ast.Other a ->
+ let unifies =
+ Unify_ast.unify_statement_dots
+ (Ast.rewrap s (Ast.DOTS([a]))) stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | Ast.Other_dots a ->
+ let unifies = Unify_ast.unify_statement_dots a stmt_dots in
+ (match unifies with
+ Unify_ast.MAYBE -> false
+ | _ -> true)
+ | _ -> true)
+ a in
+ (Ast.rewrap s (Ast.Nest(sd,w,multi,bef,a)),[Ast.Other_dots stmt_dots])
+ | Ast.Disj(stmt_dots_list) ->
+ let (dsl,dsla) =
+ List.split (List.map (function e -> get_after e a) stmt_dots_list) in
+ (Ast.rewrap s (Ast.Disj(dsl)),List.fold_left Common.union_set [] dsla)
+ | Ast.Atomic(ast) ->
+ (match Ast.unwrap ast with
+ Ast.MetaStmt(nm,keep,Ast.SequencibleAfterDots _,i) ->
+ (* check "after" information for metavar optimization *)
+ (* if the error is not desired, could just return [], then
+ the optimization (check for EF) won't take place *)
+ List.iter
+ (function
+ Ast.Other x ->
+ (match Ast.unwrap x with
+ Ast.Dots(_,_,_,_) | Ast.Nest(_,_,_,_,_) ->
+ failwith
+ "dots/nest not allowed before and after stmt metavar"
+ | _ -> ())
+ | Ast.Other_dots x ->
+ (match Ast.undots x with
+ x::_ ->
+ (match Ast.unwrap x with
+ Ast.Dots(_,_,_,_) | Ast.Nest(_,_,_,_,_) ->
+ failwith
+ ("dots/nest not allowed before and after stmt "^
+ "metavar")
+ | _ -> ())
+ | _ -> ())
+ | _ -> ())
+ a;
+ (Ast.rewrap s
+ (Ast.Atomic
+ (Ast.rewrap s
+ (Ast.MetaStmt(nm,keep,Ast.SequencibleAfterDots a,i)))),[])
+ | Ast.MetaStmt(_,_,_,_) -> (s,[])
+ | _ -> (s,[Ast.Other s]))
+ | Ast.Seq(lbrace,decls,body,rbrace) ->
+ let index = count_nested_braces s in
+ let (bd,bda) = get_after body [Ast.WParen(rbrace,index)] in
+ let (de,_) = get_after decls bda in
+ (Ast.rewrap s (Ast.Seq(lbrace,de,bd,rbrace)),
+ [Ast.WParen(lbrace,index)])
+ | Ast.Define(header,body) ->
+ let (body,_) = get_after body a in
+ (Ast.rewrap s (Ast.Define(header,body)), [Ast.Other s])
+ | Ast.IfThen(ifheader,branch,aft) ->
+ let (br,_) = get_after_e branch a in
+ (Ast.rewrap s (Ast.IfThen(ifheader,br,aft)),[Ast.Other s])
+ | Ast.IfThenElse(ifheader,branch1,els,branch2,aft) ->
+ let (br1,_) = get_after_e branch1 a in
+ let (br2,_) = get_after_e branch2 a in
+ (Ast.rewrap s (Ast.IfThenElse(ifheader,br1,els,br2,aft)),[Ast.Other s])
+ | Ast.While(header,body,aft) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.While(header,bd,aft)),[Ast.Other s])
+ | Ast.For(header,body,aft) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.For(header,bd,aft)),[Ast.Other s])
+ | Ast.Do(header,body,tail) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.Do(header,bd,tail)),[Ast.Other s])
+ | Ast.Iterator(header,body,aft) ->
+ let (bd,_) = get_after_e body a in
+ (Ast.rewrap s (Ast.Iterator(header,bd,aft)),[Ast.Other s])
+ | Ast.Switch(header,lb,cases,rb) ->
+ let cases =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let (body,_) = get_after body [] in
+ Ast.rewrap case_line (Ast.CaseLine(header,body))
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ (Ast.rewrap s (Ast.Switch(header,lb,cases,rb)),[Ast.Other s])
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ let (bd,bda) = get_after body [] in
+ let (de,_) = get_after decls bda in
+ (Ast.rewrap s (Ast.FunDecl(header,lbrace,de,bd,rbrace)),[])
+ | _ -> failwith "get_after_e: not supported"
+
+let preprocess_dots sl =
+ let (sl,_) = get_before sl [] in
+ let (sl,_) = get_after sl [] in
+ sl
+
+let preprocess_dots_e sl =
+ let (sl,_) = get_before_e sl [] in
+ let (sl,_) = get_after_e sl [] in
+ sl
+
+(* --------------------------------------------------------------------- *)
+(* various return_related things *)
+
+let rec ends_in_return stmt_list =
+ match Ast.unwrap stmt_list with
+ Ast.DOTS(x) ->
+ (match List.rev x with
+ x::_ ->
+ (match Ast.unwrap x with
+ Ast.Atomic(x) ->
+ let rec loop x =
+ match Ast.unwrap x with
+ Ast.Return(_,_) | Ast.ReturnExpr(_,_,_) -> true
+ | Ast.DisjRuleElem((_::_) as l) -> List.for_all loop l
+ | _ -> false in
+ loop x
+ | Ast.Disj(disjs) -> List.for_all ends_in_return disjs
+ | _ -> false)
+ | _ -> false)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+(* --------------------------------------------------------------------- *)
+(* expressions *)
+
+let exptymatch l make_match make_guard_match =
+ let pos = fresh_pos() in
+ let matches_guard_matches =
+ List.map
+ (function x ->
+ let pos = Ast.make_mcode pos in
+ (make_match (Ast.set_pos x (Some pos)),
+ make_guard_match (Ast.set_pos x (Some pos))))
+ l in
+ let (matches,guard_matches) = List.split matches_guard_matches in
+ let rec suffixes = function
+ [] -> []
+ | x::xs -> xs::(suffixes xs) in
+ let prefixes = List.rev (suffixes (List.rev guard_matches)) in
+ let info = (* not null *)
+ List.map2
+ (function matcher ->
+ function negates ->
+ CTL.Exists
+ (false,pos,
+ ctl_and CTL.NONSTRICT matcher
+ (ctl_not
+ (ctl_uncheck (List.fold_left ctl_or_fl CTL.False negates)))))
+ matches prefixes in
+ CTL.InnerAnd(List.fold_left ctl_or_fl CTL.False (List.rev info))
+
+(* code might be a DisjRuleElem, in which case we break it apart
+ code might contain an Exp or Ty
+ this one pushes the quantifier inwards *)
+let do_re_matches label guard res quantified minus_quantified =
+ let make_guard_match x =
+ let stmt_fvs = Ast.get_mfvs x in
+ let fvs = get_unquantified minus_quantified stmt_fvs in
+ non_saved_quantify fvs (make_match None true x) in
+ let make_match x =
+ let stmt_fvs = Ast.get_fvs x in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard fvs (make_match None guard x) in
+ ctl_and CTL.NONSTRICT (label_pred_maker label)
+ (match List.map Ast.unwrap res with
+ [] -> failwith "unexpected empty disj"
+ | Ast.Exp(e)::rest -> exptymatch res make_match make_guard_match
+ | Ast.Ty(t)::rest -> exptymatch res make_match make_guard_match
+ | all ->
+ if List.exists (function Ast.Exp(_) | Ast.Ty(_) -> true | _ -> false)
+ all
+ then failwith "unexpected exp or ty";
+ List.fold_left ctl_seqor CTL.False
+ (List.rev (List.map make_match res)))
+
+(* code might be a DisjRuleElem, in which case we break it apart
+ code doesn't contain an Exp or Ty
+ this one is for use when it is not practical to push the quantifier inwards
+ *)
+let header_match label guard code : ('a, Ast.meta_name, 'b) CTL.generic_ctl =
+ match Ast.unwrap code with
+ Ast.DisjRuleElem(res) ->
+ let make_match = make_match None guard in
+ let orop = if guard then ctl_or else ctl_seqor in
+ ctl_and CTL.NONSTRICT (label_pred_maker label)
+ (List.fold_left orop CTL.False (List.map make_match res))
+ | _ -> make_match label guard code
+
+(* --------------------------------------------------------------------- *)
+(* control structures *)
+
+let end_control_structure fvs header body after_pred
+ after_checks no_after_checks (afvs,afresh,ainh,aft) after label guard =
+ (* aft indicates what is added after the whole if, which has to be added
+ to the endif node *)
+ let (aft_needed,after_branch) =
+ match aft with
+ Ast.CONTEXT(_,Ast.NOTHING) ->
+ (false,make_seq_after2 guard after_pred after)
+ | _ ->
+ let match_endif =
+ make_match label guard
+ (make_meta_rule_elem aft (afvs,afresh,ainh)) in
+ (true,
+ make_seq_after guard after_pred
+ (After(make_seq_after guard match_endif after))) in
+ let body = body after_branch in
+ let s = guard_to_strict guard in
+ (* the code *)
+ quantify guard fvs
+ (ctl_and s header
+ (opt_and guard
+ (match (after,aft_needed) with
+ (After _,_) (* pattern doesn't end here *)
+ | (_,true) (* + code added after *) -> after_checks
+ | _ -> no_after_checks)
+ (ctl_ax_absolute s body)))
+
+let ifthen ifheader branch ((afvs,_,_,_) as aft) after
+ quantified minus_quantified label llabel slabel recurse make_match guard =
+(* "if (test) thn" becomes:
+ if(test) & AX((TrueBranch & AX thn) v FallThrough v After)
+
+ "if (test) thn; after" becomes:
+ if(test) & AX((TrueBranch & AX thn) v FallThrough v (After & AXAX after))
+ & EX After
+*)
+ (* free variables *)
+ let (efvs,bfvs) =
+ match seq_fvs quantified
+ [Ast.get_fvs ifheader;Ast.get_fvs branch;afvs] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_quantified = Common.union_set bfvs quantified in
+ let (mefvs,mbfvs) =
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs ifheader;Ast.get_mfvs branch;[]] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_mquantified = Common.union_set mbfvs minus_quantified in
+ (* if header *)
+ let if_header = quantify guard efvs (make_match ifheader) in
+ (* then branch and after *)
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let true_branch =
+ make_seq guard
+ [truepred label; recurse branch Tail new_quantified new_mquantified
+ (Some (lv,used)) llabel slabel guard] in
+ let after_pred = aftpred label in
+ let or_cases after_branch =
+ ctl_or true_branch (ctl_or (fallpred label) after_branch) in
+ let (if_header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and CTL.NONSTRICT(*???*) if_header label_pred,
+ (function body -> quantify true [lv] body))
+ else (if_header,function x -> x) in
+ wrapper
+ (end_control_structure bfvs if_header or_cases after_pred
+ (Some(ctl_ex after_pred)) None aft after label guard)
+
+let ifthenelse ifheader branch1 els branch2 ((afvs,_,_,_) as aft) after
+ quantified minus_quantified label llabel slabel recurse make_match guard =
+(* "if (test) thn else els" becomes:
+ if(test) & AX((TrueBranch & AX thn) v
+ (FalseBranch & AX (else & AX els)) v After)
+ & EX FalseBranch
+
+ "if (test) thn else els; after" becomes:
+ if(test) & AX((TrueBranch & AX thn) v
+ (FalseBranch & AX (else & AX els)) v
+ (After & AXAX after))
+ & EX FalseBranch
+ & EX After
+*)
+ (* free variables *)
+ let (e1fvs,b1fvs,s1fvs) =
+ match seq_fvs quantified
+ [Ast.get_fvs ifheader;Ast.get_fvs branch1;afvs] with
+ [(e1fvs,b1fvs);(s1fvs,b1afvs);_] ->
+ (e1fvs,Common.union_set b1fvs b1afvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let (e2fvs,b2fvs,s2fvs) =
+ (* fvs on else? *)
+ match seq_fvs quantified
+ [Ast.get_fvs ifheader;Ast.get_fvs branch2;afvs] with
+ [(e2fvs,b2fvs);(s2fvs,b2afvs);_] ->
+ (e2fvs,Common.union_set b2fvs b2afvs,s2fvs)
+ | _ -> failwith "not possible" in
+ let bothfvs = union (union b1fvs b2fvs) (intersect s1fvs s2fvs) in
+ let exponlyfvs = intersect e1fvs e2fvs in
+ let new_quantified = union bothfvs quantified in
+ (* minus free variables *)
+ let (me1fvs,mb1fvs,ms1fvs) =
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs ifheader;Ast.get_mfvs branch1;[]] with
+ [(e1fvs,b1fvs);(s1fvs,b1afvs);_] ->
+ (e1fvs,Common.union_set b1fvs b1afvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let (me2fvs,mb2fvs,ms2fvs) =
+ (* fvs on else? *)
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs ifheader;Ast.get_mfvs branch2;[]] with
+ [(e2fvs,b2fvs);(s2fvs,b2afvs);_] ->
+ (e2fvs,Common.union_set b2fvs b2afvs,s2fvs)
+ | _ -> failwith "not possible" in
+ let mbothfvs = union (union mb1fvs mb2fvs) (intersect ms1fvs ms2fvs) in
+ let new_mquantified = union mbothfvs minus_quantified in
+ (* if header *)
+ let if_header = quantify guard exponlyfvs (make_match ifheader) in
+ (* then and else branches *)
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let true_branch =
+ make_seq guard
+ [truepred label; recurse branch1 Tail new_quantified new_mquantified
+ (Some (lv,used)) llabel slabel guard] in
+ let false_branch =
+ make_seq guard
+ [falsepred label; make_match els;
+ recurse branch2 Tail new_quantified new_mquantified
+ (Some (lv,used)) llabel slabel guard] in
+ let after_pred = aftpred label in
+ let or_cases after_branch =
+ ctl_or true_branch (ctl_or false_branch after_branch) in
+ let s = guard_to_strict guard in
+ let (if_header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and CTL.NONSTRICT(*???*) if_header label_pred,
+ (function body -> quantify true [lv] body))
+ else (if_header,function x -> x) in
+ wrapper
+ (end_control_structure bothfvs if_header or_cases after_pred
+ (Some(ctl_and s (ctl_ex (falsepred label)) (ctl_ex after_pred)))
+ (Some(ctl_ex (falsepred label)))
+ aft after label guard)
+
+let forwhile header body ((afvs,_,_,_) as aft) after
+ quantified minus_quantified label recurse make_match guard =
+ let process _ =
+ (* the translation in this case is similar to that of an if with no else *)
+ (* free variables *)
+ let (efvs,bfvs) =
+ match seq_fvs quantified [Ast.get_fvs header;Ast.get_fvs body;afvs] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_quantified = Common.union_set bfvs quantified in
+ (* minus free variables *)
+ let (mefvs,mbfvs) =
+ match seq_fvs minus_quantified
+ [Ast.get_mfvs header;Ast.get_mfvs body;[]] with
+ [(efvs,b1fvs);(_,b2fvs);_] -> (efvs,Common.union_set b1fvs b2fvs)
+ | _ -> failwith "not possible" in
+ let new_mquantified = Common.union_set mbfvs minus_quantified in
+ (* loop header *)
+ let header = quantify guard efvs (make_match header) in
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let body =
+ make_seq guard
+ [inlooppred label;
+ recurse body Tail new_quantified new_mquantified
+ (Some (lv,used)) (Some (lv,used)) None guard] in
+ let after_pred = fallpred label in
+ let or_cases after_branch = ctl_or body after_branch in
+ let (header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and CTL.NONSTRICT(*???*) header label_pred,
+ (function body -> quantify true [lv] body))
+ else (header,function x -> x) in
+ wrapper
+ (end_control_structure bfvs header or_cases after_pred
+ (Some(ctl_ex after_pred)) None aft after label guard) in
+ match (Ast.unwrap body,aft) with
+ (Ast.Atomic(re),(_,_,_,Ast.CONTEXT(_,Ast.NOTHING))) ->
+ (match Ast.unwrap re with
+ Ast.MetaStmt((_,_,Ast.CONTEXT(_,Ast.NOTHING),_),
+ Type_cocci.Unitary,_,false) ->
+ let (efvs) =
+ match seq_fvs quantified [Ast.get_fvs header] with
+ [(efvs,_)] -> efvs
+ | _ -> failwith "not possible" in
+ quantify guard efvs (make_match header)
+ | _ -> process())
+ | _ -> process()
+
+(* --------------------------------------------------------------------- *)
+(* statement metavariables *)
+
+(* issue: an S metavariable that is not an if branch/loop body
+ should not match an if branch/loop body, so check that the labels
+ of the nodes before the first node matched by the S are different
+ from the label of the first node matched by the S *)
+let sequencibility body label_pred process_bef_aft = function
+ Ast.Sequencible | Ast.SequencibleAfterDots [] ->
+ body
+ (function x ->
+ (ctl_and CTL.NONSTRICT (ctl_not (ctl_back_ax label_pred)) x))
+ | Ast.SequencibleAfterDots l ->
+ (* S appears after some dots. l is the code that comes after the S.
+ want to search for that first, because S can match anything, while
+ the stuff after is probably more restricted *)
+ let afts = List.map process_bef_aft l in
+ let ors = foldl1 ctl_or afts in
+ ctl_and CTL.NONSTRICT
+ (ctl_ef (ctl_and CTL.NONSTRICT ors (ctl_back_ax label_pred)))
+ (body
+ (function x ->
+ ctl_and CTL.NONSTRICT (ctl_not (ctl_back_ax label_pred)) x))
+ | Ast.NotSequencible -> body (function x -> x)
+
+let svar_context_with_add_after stmt s label quantified d ast
+ seqible after process_bef_aft guard fvinfo =
+ let label_var = (*fresh_label_var*) string2var "_lab" in
+ let label_pred =
+ CTL.Pred (Lib_engine.Label(label_var),CTL.Control) in
+ let prelabel_pred =
+ CTL.Pred (Lib_engine.PrefixLabel(label_var),CTL.Control) in
+ let matcher d = make_match None guard (make_meta_rule_elem d fvinfo) in
+ let full_metamatch = matcher d in
+ let first_metamatch =
+ matcher
+ (match d with
+ Ast.CONTEXT(pos,Ast.BEFOREAFTER(bef,_)) ->
+ Ast.CONTEXT(pos,Ast.BEFORE(bef))
+ | Ast.CONTEXT(pos,_) -> Ast.CONTEXT(pos,Ast.NOTHING)
+ | Ast.MINUS(_,_) | Ast.PLUS -> failwith "not possible") in
+ let middle_metamatch =
+ matcher
+ (match d with
+ Ast.CONTEXT(pos,_) -> Ast.CONTEXT(pos,Ast.NOTHING)
+ | Ast.MINUS(_,_) | Ast.PLUS -> failwith "not possible") in
+ let last_metamatch =
+ matcher
+ (match d with
+ Ast.CONTEXT(pos,Ast.BEFOREAFTER(_,aft)) ->
+ Ast.CONTEXT(pos,Ast.AFTER(aft))
+ | Ast.CONTEXT(_,_) -> d
+ | Ast.MINUS(_,_) | Ast.PLUS -> failwith "not possible") in
+
+ let rest_nodes =
+ ctl_and CTL.NONSTRICT middle_metamatch prelabel_pred in
+ let left_or = (* the whole statement is one node *)
+ make_seq guard
+ [full_metamatch; and_after guard (ctl_not prelabel_pred) after] in
+ let right_or = (* the statement covers multiple nodes *)
+ make_seq guard
+ [first_metamatch;
+ ctl_au CTL.NONSTRICT
+ rest_nodes
+ (make_seq guard
+ [ctl_and CTL.NONSTRICT last_metamatch label_pred;
+ and_after guard
+ (ctl_not prelabel_pred) after])] in
+ let body f =
+ ctl_and CTL.NONSTRICT label_pred
+ (f (ctl_and CTL.NONSTRICT
+ (make_raw_match label false ast) (ctl_or left_or right_or))) in
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard (label_var::fvs)
+ (sequencibility body label_pred process_bef_aft seqible)
+
+let svar_minus_or_no_add_after stmt s label quantified d ast
+ seqible after process_bef_aft guard fvinfo =
+ let label_var = (*fresh_label_var*) string2var "_lab" in
+ let label_pred =
+ CTL.Pred (Lib_engine.Label(label_var),CTL.Control) in
+ let prelabel_pred =
+ CTL.Pred (Lib_engine.PrefixLabel(label_var),CTL.Control) in
+ let matcher d = make_match None guard (make_meta_rule_elem d fvinfo) in
+ let pure_d =
+ (* don't have to put anything before the beginning, so don't have to
+ distinguish the first node. so don't have to bother about paths,
+ just use the label. label ensures that found nodes match up with
+ what they should because it is in the lhs of the andany. *)
+ match d with
+ Ast.MINUS(pos,[]) -> true
+ | Ast.CONTEXT(pos,Ast.NOTHING) -> true
+ | _ -> false in
+ let ender =
+ match (pure_d,after) with
+ (true,Tail) | (true,End) | (true,VeryEnd) ->
+ (* the label sharing makes it safe to use AndAny *)
+ CTL.HackForStmt(CTL.FORWARD,CTL.NONSTRICT,
+ ctl_and CTL.NONSTRICT label_pred
+ (make_raw_match label false ast),
+ ctl_and CTL.NONSTRICT (matcher d) prelabel_pred)
+ | _ ->
+ (* more safe but less efficient *)
+ let first_metamatch = matcher d in
+ let rest_metamatch =
+ matcher
+ (match d with
+ Ast.MINUS(pos,_) -> Ast.MINUS(pos,[])
+ | Ast.CONTEXT(pos,_) -> Ast.CONTEXT(pos,Ast.NOTHING)
+ | Ast.PLUS -> failwith "not possible") in
+ let rest_nodes = ctl_and CTL.NONSTRICT rest_metamatch prelabel_pred in
+ let last_node = and_after guard (ctl_not prelabel_pred) after in
+ (ctl_and CTL.NONSTRICT (make_raw_match label false ast)
+ (make_seq guard
+ [first_metamatch;
+ ctl_au CTL.NONSTRICT rest_nodes last_node])) in
+ let body f = ctl_and CTL.NONSTRICT label_pred (f ender) in
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard (label_var::fvs)
+ (sequencibility body label_pred process_bef_aft seqible)
+
+(* --------------------------------------------------------------------- *)
+(* dots and nests *)
+
+let dots_au is_strict toend label s wrapcode x seq_after y quantifier =
+ let matchgoto = gotopred None in
+ let matchbreak =
+ make_match None false
+ (wrapcode
+ (Ast.Break(Ast.make_mcode "break",Ast.make_mcode ";"))) in
+ let matchcontinue =
+ make_match None false
+ (wrapcode
+ (Ast.Continue(Ast.make_mcode "continue",Ast.make_mcode ";"))) in
+ let stop_early v =
+ if !exists = Exists
+ then CTL.False
+ else if toend
+ then CTL.Or(aftpred label,exitpred label)
+ else if is_strict
+ then aftpred label
+ else
+ let lv = get_label_ctr() in
+ let labelpred = CTL.Pred(Lib_engine.Label lv,CTL.Control) in
+ let preflabelpred = label_pred_maker (Some (lv,ref true)) in
+ ctl_or (aftpred label)
+ (quantify false [lv]
+ (ctl_and CTL.NONSTRICT
+ (ctl_and CTL.NONSTRICT (truepred label) labelpred)
+ (ctl_au CTL.NONSTRICT
+ (ctl_and CTL.NONSTRICT (ctl_not v) preflabelpred)
+ (ctl_and CTL.NONSTRICT preflabelpred
+ (ctl_or (retpred None)
+ (if !Flag_engine.only_return_is_error_exit
+ then CTL.True
+ else
+ (ctl_or matchcontinue
+ (ctl_and CTL.NONSTRICT
+ (ctl_or matchgoto matchbreak)
+ (ctl_ag s (ctl_not seq_after)))))))))) in
+ let v = get_let_ctr() in
+ let op = if quantifier = !exists then ctl_au else ctl_anti_au in
+ op s x (CTL.Let(v,y,ctl_or (CTL.Ref v) (stop_early (CTL.Ref v))))
+
+let rec dots_and_nests plus nest whencodes bef aft dotcode after label
+ process_bef_aft statement_list statement guard quantified wrapcode =
+ let ctl_and_ns = ctl_and CTL.NONSTRICT in
+ (* proces bef_aft *)
+ let shortest l =
+ List.fold_left ctl_or_fl CTL.False (List.map process_bef_aft l) in
+ let bef_aft = (* to be negated *)
+ try
+ let _ =
+ List.find
+ (function Ast.WhenModifier(Ast.WhenAny) -> true | _ -> false)
+ whencodes in
+ CTL.False
+ with Not_found -> shortest (Common.union_set bef aft) in
+ let is_strict =
+ List.exists
+ (function Ast.WhenModifier(Ast.WhenStrict) -> true | _ -> false)
+ whencodes in
+ let check_quantifier quant other =
+ if List.exists
+ (function Ast.WhenModifier(x) -> x = quant | _ -> false)
+ whencodes
+ then
+ if List.exists
+ (function Ast.WhenModifier(x) -> x = other | _ -> false)
+ whencodes
+ then failwith "inconsistent annotation on dots"
+ else true
+ else false in
+ let quantifier =
+ if check_quantifier Ast.WhenExists Ast.WhenForall
+ then Exists
+ else
+ if check_quantifier Ast.WhenForall Ast.WhenExists
+ then Forall
+ else !exists in
+ (* the following is used when we find a goto, etc and consider accepting
+ without finding the rest of the pattern *)
+ let aft = shortest aft in
+ (* process whencode *)
+ let labelled = label_pred_maker label in
+ let whencodes arg =
+ let (poswhen,negwhen) =
+ List.fold_left
+ (function (poswhen,negwhen) ->
+ function
+ Ast.WhenNot whencodes ->
+ (poswhen,ctl_or (statement_list whencodes) negwhen)
+ | Ast.WhenAlways stm ->
+ (ctl_and CTL.NONSTRICT (statement stm) poswhen,negwhen)
+ | Ast.WhenModifier(_) -> (poswhen,negwhen)
+ | Ast.WhenNotTrue(e) ->
+ (poswhen,
+ ctl_or (whencond_true e label guard quantified) negwhen)
+ | Ast.WhenNotFalse(e) ->
+ (poswhen,
+ ctl_or (whencond_false e label guard quantified) negwhen))
+ (CTL.True,bef_aft) (List.rev whencodes) in
+ let poswhen = ctl_and_ns arg poswhen in
+ let negwhen =
+(* if !exists
+ then*)
+ (* add in After, because it's not part of the program *)
+ ctl_or (aftpred label) negwhen
+ (*else negwhen*) in
+ ctl_and_ns poswhen (ctl_not negwhen) in
+ (* process dot code, if any *)
+ let dotcode =
+ match (dotcode,guard) with
+ (None,_) | (_,true) -> CTL.True
+ | (Some dotcode,_) -> dotcode in
+ (* process nest code, if any *)
+ (* whencode goes in the negated part of the nest; if no nest, just goes
+ on the "true" in between code *)
+ let plus_var = if plus then get_label_ctr() else string2var "" in
+ let plus_var2 = if plus then get_label_ctr() else string2var "" in
+ let ornest =
+ match (nest,guard && not plus) with
+ (None,_) | (_,true) -> whencodes CTL.True
+ | (Some nest,false) ->
+ let v = get_let_ctr() in
+ let is_plus x =
+ if plus
+ then
+ (* the idea is that BindGood is sort of a witness; a witness to
+ having found the subterm in at least one place. If there is
+ not a witness, then there is a risk that it will get thrown
+ away, if it is merged with a node that has an empty
+ environment. See tests/nestplus. But this all seems
+ rather suspicious *)
+ CTL.And(CTL.NONSTRICT,x,
+ CTL.Exists(true,plus_var2,
+ CTL.Pred(Lib_engine.BindGood(plus_var),
+ CTL.Modif plus_var2)))
+ else x in
+ CTL.Let(v,nest,
+ CTL.Or(is_plus (CTL.Ref v),
+ whencodes (CTL.Not(ctl_uncheck (CTL.Ref v))))) in
+ let plus_modifier x =
+ if plus
+ then
+ CTL.Exists
+ (false,plus_var,
+ (CTL.And
+ (CTL.NONSTRICT,x,
+ CTL.Not(CTL.Pred(Lib_engine.BindBad(plus_var),CTL.Control)))))
+ else x in
+
+ let ender =
+ match after with
+ After f -> f
+ | Guard f -> ctl_uncheck f
+ | VeryEnd ->
+ let exit = endpred label in
+ let errorexit = exitpred label in
+ ctl_or exit errorexit
+ (* not at all sure what the next two mean... *)
+ | End -> CTL.True
+ | Tail ->
+ (match label with
+ Some (lv,used) -> used := true;
+ ctl_or (CTL.Pred(Lib_engine.Label lv,CTL.Control))
+ (ctl_back_ex (ctl_or (retpred label) (gotopred label)))
+ | None -> endpred label)
+ (* was the following, but not clear why sgrep should allow
+ incomplete patterns
+ let exit = endpred label in
+ let errorexit = exitpred label in
+ if !exists
+ then ctl_or exit errorexit (* end anywhere *)
+ else exit (* end at the real end of the function *) *) in
+ plus_modifier
+ (dots_au is_strict ((after = Tail) or (after = VeryEnd))
+ label (guard_to_strict guard) wrapcode
+ (ctl_and_ns dotcode (ctl_and_ns ornest labelled))
+ aft ender quantifier)
+
+and get_whencond_exps e =
+ match Ast.unwrap e with
+ Ast.Exp e -> [e]
+ | Ast.DisjRuleElem(res) ->
+ List.fold_left Common.union_set [] (List.map get_whencond_exps res)
+ | _ -> failwith "not possible"
+
+and make_whencond_headers e e1 label guard quantified =
+ let fvs = Ast.get_fvs e in
+ let header_pred h =
+ quantify guard (get_unquantified quantified fvs)
+ (make_match label guard h) in
+ let if_header e1 =
+ header_pred
+ (Ast.rewrap e
+ (Ast.IfHeader
+ (Ast.make_mcode "if",
+ Ast.make_mcode "(",e1,Ast.make_mcode ")"))) in
+ let while_header e1 =
+ header_pred
+ (Ast.rewrap e
+ (Ast.WhileHeader
+ (Ast.make_mcode "while",
+ Ast.make_mcode "(",e1,Ast.make_mcode ")"))) in
+ let for_header e1 =
+ header_pred
+ (Ast.rewrap e
+ (Ast.ForHeader
+ (Ast.make_mcode "for",Ast.make_mcode "(",None,Ast.make_mcode ";",
+ Some e1,Ast.make_mcode ";",None,Ast.make_mcode ")"))) in
+ let if_headers =
+ List.fold_left ctl_or CTL.False (List.map if_header e1) in
+ let while_headers =
+ List.fold_left ctl_or CTL.False (List.map while_header e1) in
+ let for_headers =
+ List.fold_left ctl_or CTL.False (List.map for_header e1) in
+ (if_headers, while_headers, for_headers)
+
+and whencond_true e label guard quantified =
+ let e1 = get_whencond_exps e in
+ let (if_headers, while_headers, for_headers) =
+ make_whencond_headers e e1 label guard quantified in
+ ctl_or
+ (ctl_and CTL.NONSTRICT (truepred label) (ctl_back_ex if_headers))
+ (ctl_and CTL.NONSTRICT
+ (inlooppred label) (ctl_back_ex (ctl_or while_headers for_headers)))
+
+and whencond_false e label guard quantified =
+ let e1 = get_whencond_exps e in
+ let (if_headers, while_headers, for_headers) =
+ make_whencond_headers e e1 label guard quantified in
+ ctl_or (ctl_and CTL.NONSTRICT (falsepred label) (ctl_back_ex if_headers))
+ (ctl_and CTL.NONSTRICT (fallpred label)
+ (ctl_or (ctl_back_ex if_headers)
+ (ctl_or (ctl_back_ex while_headers) (ctl_back_ex for_headers))))
+
+(* --------------------------------------------------------------------- *)
+(* the main translation loop *)
+
+let rec statement_list stmt_list after quantified minus_quantified
+ label llabel slabel dots_before guard =
+ let isdots x =
+ (* include Disj to be on the safe side *)
+ match Ast.unwrap x with
+ Ast.Dots _ | Ast.Nest _ | Ast.Disj _ -> true | _ -> false in
+ let compute_label l e db = if db or isdots e then l else None in
+ match Ast.unwrap stmt_list with
+ Ast.DOTS(x) ->
+ let rec loop quantified minus_quantified dots_before label llabel slabel
+ = function
+ ([],_,_) -> (match after with After f -> f | _ -> CTL.True)
+ | ([e],_,_) ->
+ statement e after quantified minus_quantified
+ (compute_label label e dots_before)
+ llabel slabel guard
+ | (e::sl,fv::fvs,mfv::mfvs) ->
+ let shared = intersectll fv fvs in
+ let unqshared = get_unquantified quantified shared in
+ let new_quantified = Common.union_set unqshared quantified in
+ let minus_shared = intersectll mfv mfvs in
+ let munqshared =
+ get_unquantified minus_quantified minus_shared in
+ let new_mquantified =
+ Common.union_set munqshared minus_quantified in
+ quantify guard unqshared
+ (statement e
+ (After
+ (let (label1,llabel1,slabel1) =
+ match Ast.unwrap e with
+ Ast.Atomic(re) ->
+ (match Ast.unwrap re with
+ Ast.Goto _ -> (None,None,None)
+ | _ -> (label,llabel,slabel))
+ | _ -> (label,llabel,slabel) in
+ loop new_quantified new_mquantified (isdots e)
+ label1 llabel1 slabel1
+ (sl,fvs,mfvs)))
+ new_quantified new_mquantified
+ (compute_label label e dots_before) llabel slabel guard)
+ | _ -> failwith "not possible" in
+ loop quantified minus_quantified dots_before
+ label llabel slabel
+ (x,List.map Ast.get_fvs x,List.map Ast.get_mfvs x)
+ | Ast.CIRCLES(x) -> failwith "not supported"
+ | Ast.STARS(x) -> failwith "not supported"
+
+(* llabel is the label of the enclosing loop and slabel is the label of the
+ enclosing switch *)
+and statement stmt after quantified minus_quantified
+ label llabel slabel guard =
+ let ctl_au = ctl_au CTL.NONSTRICT in
+ let ctl_ax = ctl_ax CTL.NONSTRICT in
+ let ctl_and = ctl_and CTL.NONSTRICT in
+ let make_seq = make_seq guard in
+ let make_seq_after = make_seq_after guard in
+ let real_make_match = make_match in
+ let make_match = header_match label guard in
+
+ let dots_done = ref false in (* hack for dots cases we can easily handle *)
+
+ let term =
+ match Ast.unwrap stmt with
+ Ast.Atomic(ast) ->
+ (match Ast.unwrap ast with
+ (* the following optimisation is not a good idea, because when S
+ is alone, we would like it not to match a declaration.
+ this makes more matching for things like when (...) S, but perhaps
+ that matching is not so costly anyway *)
+ (*Ast.MetaStmt(_,Type_cocci.Unitary,_,false) when guard -> CTL.True*)
+ | Ast.MetaStmt((s,_,(Ast.CONTEXT(_,Ast.BEFOREAFTER(_,_)) as d),_),
+ keep,seqible,_)
+ | Ast.MetaStmt((s,_,(Ast.CONTEXT(_,Ast.AFTER(_)) as d),_),
+ keep,seqible,_)->
+ svar_context_with_add_after stmt s label quantified d ast seqible
+ after
+ (process_bef_aft quantified minus_quantified
+ label llabel slabel true)
+ guard
+ (Ast.get_fvs stmt, Ast.get_fresh stmt, Ast.get_inherited stmt)
+
+ | Ast.MetaStmt((s,_,d,_),keep,seqible,_) ->
+ svar_minus_or_no_add_after stmt s label quantified d ast seqible
+ after
+ (process_bef_aft quantified minus_quantified
+ label llabel slabel true)
+ guard
+ (Ast.get_fvs stmt, Ast.get_fresh stmt, Ast.get_inherited stmt)
+
+ | _ ->
+ let term =
+ match Ast.unwrap ast with
+ Ast.DisjRuleElem(res) ->
+ do_re_matches label guard res quantified minus_quantified
+ | Ast.Exp(_) | Ast.Ty(_) ->
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ CTL.InnerAnd(quantify guard fvs (make_match ast))
+ | _ ->
+ let stmt_fvs = Ast.get_fvs stmt in
+ let fvs = get_unquantified quantified stmt_fvs in
+ quantify guard fvs (make_match ast) in
+ match Ast.unwrap ast with
+ Ast.Break(brk,semi) ->
+ (match (llabel,slabel) with
+ (_,Some(lv,used)) -> (* use switch label if there is one *)
+ ctl_and term (bclabel_pred_maker slabel)
+ | _ -> ctl_and term (bclabel_pred_maker llabel))
+ | Ast.Continue(brk,semi) -> ctl_and term (bclabel_pred_maker llabel)
+ | Ast.Return((_,info,retmc,pos),(_,_,semmc,_)) ->
+ (* discard pattern that comes after return *)
+ let normal_res = make_seq_after term after in
+ (* the following code tries to propagate the modifications on
+ return; to a close brace, in the case where the final return
+ is absent *)
+ let new_mc =
+ match (retmc,semmc) with
+ (Ast.MINUS(_,l1),Ast.MINUS(_,l2)) when !Flag.sgrep_mode2 ->
+ (* in sgrep mode, we can propagate the - *)
+ Some (Ast.MINUS(Ast.NoPos,l1@l2))
+ | (Ast.MINUS(_,l1),Ast.MINUS(_,l2))
+ | (Ast.CONTEXT(_,Ast.BEFORE(l1)),
+ Ast.CONTEXT(_,Ast.AFTER(l2))) ->
+ Some (Ast.CONTEXT(Ast.NoPos,Ast.BEFORE(l1@l2)))
+ | (Ast.CONTEXT(_,Ast.BEFORE(_)),Ast.CONTEXT(_,Ast.NOTHING))
+ | (Ast.CONTEXT(_,Ast.NOTHING),Ast.CONTEXT(_,Ast.NOTHING)) ->
+ Some retmc
+ | (Ast.CONTEXT(_,Ast.NOTHING),Ast.CONTEXT(_,Ast.AFTER(l))) ->
+ Some (Ast.CONTEXT(Ast.NoPos,Ast.BEFORE(l)))
+ | _ -> None in
+ let ret = Ast.make_mcode "return" in
+ let edots =
+ Ast.rewrap ast (Ast.Edots(Ast.make_mcode "...",None)) in
+ let semi = Ast.make_mcode ";" in
+ let simple_return =
+ make_match(Ast.rewrap ast (Ast.Return(ret,semi))) in
+ let return_expr =
+ make_match(Ast.rewrap ast (Ast.ReturnExpr(ret,edots,semi))) in
+ (match new_mc with
+ Some new_mc ->
+ let exit = endpred None in
+ let mod_rbrace =
+ Ast.rewrap ast (Ast.SeqEnd (("}",info,new_mc,pos))) in
+ let stripped_rbrace =
+ Ast.rewrap ast (Ast.SeqEnd(Ast.make_mcode "}")) in
+ ctl_or normal_res
+ (ctl_and (make_match mod_rbrace)
+ (ctl_and
+ (ctl_back_ax
+ (ctl_not
+ (ctl_uncheck
+ (ctl_or simple_return return_expr))))
+ (ctl_au
+ (make_match stripped_rbrace)
+ (* error exit not possible; it is in the middle
+ of code, so a return is needed *)
+ exit)))
+ | _ ->
+ (* some change in the middle of the return, so have to
+ find an actual return *)
+ normal_res)
+ | _ ->
+ (* should try to deal with the dots_bef_aft problem elsewhere,
+ but don't have the courage... *)
+ let term =
+ if guard
+ then term
+ else
+ do_between_dots stmt term End
+ quantified minus_quantified label llabel slabel guard in
+ dots_done := true;
+ make_seq_after term after)
+ | Ast.Seq(lbrace,decls,body,rbrace) ->
+ let (lbfvs,b1fvs,b2fvs,b3fvs,rbfvs) =
+ match
+ seq_fvs quantified
+ [Ast.get_fvs lbrace;Ast.get_fvs decls;
+ Ast.get_fvs body;Ast.get_fvs rbrace]
+ with
+ [(lbfvs,b1fvs);(_,b2fvs);(_,b3fvs);(rbfvs,_)] ->
+ (lbfvs,b1fvs,b2fvs,b3fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let (mlbfvs,mb1fvs,mb2fvs,mb3fvs,mrbfvs) =
+ match
+ seq_fvs minus_quantified
+ [Ast.get_mfvs lbrace;Ast.get_mfvs decls;
+ Ast.get_mfvs body;Ast.get_mfvs rbrace]
+ with
+ [(lbfvs,b1fvs);(_,b2fvs);(_,b3fvs);(rbfvs,_)] ->
+ (lbfvs,b1fvs,b2fvs,b3fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let pv = count_nested_braces stmt in
+ let lv = get_label_ctr() in
+ let paren_pred = CTL.Pred(Lib_engine.Paren pv,CTL.Control) in
+ let label_pred = CTL.Pred(Lib_engine.Label lv,CTL.Control) in
+ let start_brace =
+ ctl_and
+ (quantify guard lbfvs (make_match lbrace))
+ (ctl_and paren_pred label_pred) in
+ let empty_rbrace =
+ match Ast.unwrap rbrace with
+ Ast.SeqEnd((data,info,_,pos)) ->
+ Ast.rewrap rbrace(Ast.SeqEnd(Ast.make_mcode data))
+ | _ -> failwith "unexpected close brace" in
+ let end_brace =
+ (* label is not needed; paren_pred is enough *)
+ quantify guard rbfvs
+ (ctl_au (make_match empty_rbrace)
+ (ctl_and
+ (real_make_match None guard rbrace)
+ paren_pred)) in
+ let new_quantified2 =
+ Common.union_set b1fvs (Common.union_set b2fvs quantified) in
+ let new_quantified3 = Common.union_set b3fvs new_quantified2 in
+ let new_mquantified2 =
+ Common.union_set mb1fvs (Common.union_set mb2fvs minus_quantified) in
+ let new_mquantified3 = Common.union_set mb3fvs new_mquantified2 in
+ let pattern_as_given =
+ let new_quantified2 = Common.union_set [pv] new_quantified2 in
+ let new_quantified3 = Common.union_set [pv] new_quantified3 in
+ quantify true [pv;lv]
+ (quantify guard b1fvs
+ (make_seq
+ [start_brace;
+ quantify guard b2fvs
+ (statement_list decls
+ (After
+ (quantify guard b3fvs
+ (statement_list body
+ (After (make_seq_after end_brace after))
+ new_quantified3 new_mquantified3
+ (Some (lv,ref true)) (* label mostly useful *)
+ llabel slabel true guard)))
+ new_quantified2 new_mquantified2
+ (Some (lv,ref true)) llabel slabel false guard)])) in
+ if ends_in_return body
+ then
+ (* matching error handling code *)
+ (* Cases:
+ 1. The pattern as given
+ 2. A goto, and then some close braces, and then the pattern as
+ given, but without the braces (only possible if there are no
+ decls, and open and close braces are unmodified)
+ 3. Part of the pattern as given, then a goto, and then the rest
+ of the pattern. For this case, we just check that all paths have
+ a goto within the current braces. checking for a goto at every
+ point in the pattern seems expensive and not worthwhile. *)
+ let pattern2 =
+ let body = preprocess_dots body in (* redo, to drop braces *)
+ make_seq
+ [gotopred label;
+ ctl_au
+ (make_match empty_rbrace)
+ (ctl_ax (* skip the destination label *)
+ (quantify guard b3fvs
+ (statement_list body End
+ new_quantified3 new_mquantified3 None llabel slabel
+ true guard)))] in
+ let pattern3 =
+ let new_quantified2 = Common.union_set [pv] new_quantified2 in
+ let new_quantified3 = Common.union_set [pv] new_quantified3 in
+ quantify true [pv;lv]
+ (quantify guard b1fvs
+ (make_seq
+ [start_brace;
+ ctl_and
+ (CTL.AU (* want AF even for sgrep *)
+ (CTL.FORWARD,CTL.STRICT,
+ CTL.Pred(Lib_engine.PrefixLabel(lv),CTL.Control),
+ ctl_and (* brace must be eventually after goto *)
+ (gotopred (Some (lv,ref true)))
+ (* want AF even for sgrep *)
+ (CTL.AF(CTL.FORWARD,CTL.STRICT,end_brace))))
+ (quantify guard b2fvs
+ (statement_list decls
+ (After
+ (quantify guard b3fvs
+ (statement_list body Tail
+ (*After
+ (make_seq_after
+ nopv_end_brace after)*)
+ new_quantified3 new_mquantified3
+ None llabel slabel true guard)))
+ new_quantified2 new_mquantified2
+ (Some (lv,ref true))
+ llabel slabel false guard))])) in
+ ctl_or pattern_as_given
+ (match Ast.unwrap decls with
+ Ast.DOTS([]) -> ctl_or pattern2 pattern3
+ | Ast.DOTS(l) -> pattern3
+ | _ -> failwith "circles and stars not supported")
+ else pattern_as_given
+ | Ast.IfThen(ifheader,branch,aft) ->
+ ifthen ifheader branch aft after quantified minus_quantified
+ label llabel slabel statement make_match guard
+
+ | Ast.IfThenElse(ifheader,branch1,els,branch2,aft) ->
+ ifthenelse ifheader branch1 els branch2 aft after quantified
+ minus_quantified label llabel slabel statement make_match guard
+
+ | Ast.While(header,body,aft) | Ast.For(header,body,aft)
+ | Ast.Iterator(header,body,aft) ->
+ forwhile header body aft after quantified minus_quantified
+ label statement make_match guard
+
+ | Ast.Disj(stmt_dots_list) -> (* list shouldn't be empty *)
+ ctl_and
+ (label_pred_maker label)
+ (List.fold_left ctl_seqor CTL.False
+ (List.map
+ (function sl ->
+ statement_list sl after quantified minus_quantified label
+ llabel slabel true guard)
+ stmt_dots_list))
+
+ | Ast.Nest(stmt_dots,whencode,multi,bef,aft) ->
+ (* label in recursive call is None because label check is already
+ wrapped around the corresponding code *)
+
+ let bfvs =
+ match seq_fvs quantified [Ast.get_wcfvs whencode;Ast.get_fvs stmt_dots]
+ with
+ [(wcfvs,bothfvs);(bdfvs,_)] -> bothfvs
+ | _ -> failwith "not possible" in
+
+ (* no minus version because when code doesn't contain any minus code *)
+ let new_quantified = Common.union_set bfvs quantified in
+
+ quantify guard bfvs
+ (let dots_pattern =
+ statement_list stmt_dots (a2n after) new_quantified minus_quantified
+ None llabel slabel true guard in
+ dots_and_nests multi
+ (Some dots_pattern) whencode bef aft None after label
+ (process_bef_aft new_quantified minus_quantified
+ None llabel slabel true)
+ (function x ->
+ statement_list x Tail new_quantified minus_quantified None
+ llabel slabel true true)
+ (function x ->
+ statement x Tail new_quantified minus_quantified None
+ llabel slabel true)
+ guard quantified
+ (function x -> Ast.set_fvs [] (Ast.rewrap stmt x)))
+
+ | Ast.Dots((_,i,d,_),whencodes,bef,aft) ->
+ let dot_code =
+ match d with
+ Ast.MINUS(_,_) ->
+ (* no need for the fresh metavar, but ... is a bit wierd as a
+ variable name *)
+ Some(make_match (make_meta_rule_elem d ([],[],[])))
+ | _ -> None in
+ dots_and_nests false None whencodes bef aft dot_code after label
+ (process_bef_aft quantified minus_quantified None llabel slabel true)
+ (function x ->
+ statement_list x Tail quantified minus_quantified
+ None llabel slabel true true)
+ (function x ->
+ statement x Tail quantified minus_quantified None llabel slabel true)
+ guard quantified
+ (function x -> Ast.set_fvs [] (Ast.rewrap stmt x))
+
+ | Ast.Switch(header,lb,cases,rb) ->
+ let rec intersect_all = function
+ [] -> []
+ | [x] -> x
+ | x::xs -> intersect x (intersect_all xs) in
+ let rec union_all l = List.fold_left union [] l in
+ (* start normal variables *)
+ let header_fvs = Ast.get_fvs header in
+ let lb_fvs = Ast.get_fvs lb in
+ let case_fvs = List.map Ast.get_fvs cases in
+ let rb_fvs = Ast.get_fvs rb in
+ let (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) =
+ List.fold_left
+ (function (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) ->
+ function case_fvs ->
+ match seq_fvs quantified [header_fvs;lb_fvs;case_fvs;rb_fvs] with
+ [(efvs,b1fvs);(lbfvs,b2fvs);(casefvs,b3fvs);(rbfvs,_)] ->
+ (efvs::all_efvs,b1fvs::all_b1fvs,lbfvs::all_lbfvs,
+ b2fvs::all_b2fvs,casefvs::all_casefvs,b3fvs::all_b3fvs,
+ rbfvs::all_rbfvs)
+ | _ -> failwith "not possible")
+ ([],[],[],[],[],[],[]) case_fvs in
+ let (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) =
+ (List.rev all_efvs,List.rev all_b1fvs,List.rev all_lbfvs,
+ List.rev all_b2fvs,List.rev all_casefvs,List.rev all_b3fvs,
+ List.rev all_rbfvs) in
+ let exponlyfvs = intersect_all all_efvs in
+ let lbonlyfvs = intersect_all all_lbfvs in
+(* don't do anything with right brace. Hope there is no + code on it *)
+(* let rbonlyfvs = intersect_all all_rbfvs in*)
+ let b1fvs = union_all all_b1fvs in
+ let new1_quantified = union b1fvs quantified in
+ let b2fvs = union (union_all all_b1fvs) (intersect_all all_casefvs) in
+ let new2_quantified = union b2fvs new1_quantified in
+(* let b3fvs = union_all all_b3fvs in*)
+ (* ------------------- start minus free variables *)
+ let header_mfvs = Ast.get_mfvs header in
+ let lb_mfvs = Ast.get_mfvs lb in
+ let case_mfvs = List.map Ast.get_mfvs cases in
+ let rb_mfvs = Ast.get_mfvs rb in
+ let (all_mefvs,all_mb1fvs,all_mlbfvs,all_mb2fvs,
+ all_mcasefvs,all_mb3fvs,all_mrbfvs) =
+ List.fold_left
+ (function (all_efvs,all_b1fvs,all_lbfvs,all_b2fvs,
+ all_casefvs,all_b3fvs,all_rbfvs) ->
+ function case_mfvs ->
+ match
+ seq_fvs quantified
+ [header_mfvs;lb_mfvs;case_mfvs;rb_mfvs] with
+ [(efvs,b1fvs);(lbfvs,b2fvs);(casefvs,b3fvs);(rbfvs,_)] ->
+ (efvs::all_efvs,b1fvs::all_b1fvs,lbfvs::all_lbfvs,
+ b2fvs::all_b2fvs,casefvs::all_casefvs,b3fvs::all_b3fvs,
+ rbfvs::all_rbfvs)
+ | _ -> failwith "not possible")
+ ([],[],[],[],[],[],[]) case_mfvs in
+ let (all_mefvs,all_mb1fvs,all_mlbfvs,all_mb2fvs,
+ all_mcasefvs,all_mb3fvs,all_mrbfvs) =
+ (List.rev all_mefvs,List.rev all_mb1fvs,List.rev all_mlbfvs,
+ List.rev all_mb2fvs,List.rev all_mcasefvs,List.rev all_mb3fvs,
+ List.rev all_mrbfvs) in
+(* don't do anything with right brace. Hope there is no + code on it *)
+(* let rbonlyfvs = intersect_all all_rbfvs in*)
+ let mb1fvs = union_all all_mb1fvs in
+ let new1_mquantified = union mb1fvs quantified in
+ let mb2fvs = union (union_all all_mb1fvs) (intersect_all all_mcasefvs) in
+ let new2_mquantified = union mb2fvs new1_mquantified in
+(* let b3fvs = union_all all_b3fvs in*)
+ (* ------------------- end collection of free variables *)
+ let switch_header = quantify guard exponlyfvs (make_match header) in
+ let lb = quantify guard lbonlyfvs (make_match lb) in
+(* let rb = quantify guard rbonlyfvs (make_match rb) in*)
+ let case_headers =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let e1fvs =
+ match seq_fvs new2_quantified [Ast.get_fvs header] with
+ [(e1fvs,_)] -> e1fvs
+ | _ -> failwith "not possible" in
+ quantify guard e1fvs (real_make_match label true header)
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ let no_header =
+ ctl_not (List.fold_left ctl_or_fl CTL.False case_headers) in
+ let lv = get_label_ctr() in
+ let used = ref false in
+ let case_code =
+ List.map
+ (function case_line ->
+ match Ast.unwrap case_line with
+ Ast.CaseLine(header,body) ->
+ let (e1fvs,b1fvs,s1fvs) =
+ let fvs = [Ast.get_fvs header;Ast.get_fvs body] in
+ match seq_fvs new2_quantified fvs with
+ [(e1fvs,b1fvs);(s1fvs,_)] -> (e1fvs,b1fvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let (me1fvs,mb1fvs,ms1fvs) =
+ let fvs = [Ast.get_mfvs header;Ast.get_mfvs body] in
+ match seq_fvs new2_mquantified fvs with
+ [(e1fvs,b1fvs);(s1fvs,_)] -> (e1fvs,b1fvs,s1fvs)
+ | _ -> failwith "not possible" in
+ let case_header =
+ quantify guard e1fvs (make_match header) in
+ let new3_quantified = union b1fvs new2_quantified in
+ let new3_mquantified = union mb1fvs new2_mquantified in
+ let body =
+ statement_list body Tail
+ new3_quantified new3_mquantified label llabel
+ (Some (lv,used)) true(*?*) guard in
+ quantify guard b1fvs (make_seq [case_header; body])
+ | Ast.OptCase(case_line) -> failwith "not supported")
+ cases in
+ let default_required =
+ if List.exists
+ (function case ->
+ match Ast.unwrap case with
+ Ast.CaseLine(header,_) ->
+ (match Ast.unwrap header with
+ Ast.Default(_,_) -> true
+ | _ -> false)
+ | _ -> false)
+ cases
+ then function x -> x
+ else function x -> ctl_or (fallpred label) x in
+ let after_pred = aftpred label in
+ let body after_branch =
+ ctl_or
+ (default_required
+ (quantify guard b2fvs
+ (make_seq
+ [ctl_and lb
+ (List.fold_left ctl_and CTL.True
+ (List.map ctl_ex case_headers));
+ List.fold_left ctl_or_fl no_header case_code])))
+ after_branch in
+ let aft =
+ (rb_fvs,Ast.get_fresh rb,Ast.get_inherited rb,
+ match Ast.unwrap rb with
+ Ast.SeqEnd(rb) -> Ast.get_mcodekind rb
+ | _ -> failwith "not possible") in
+ let (switch_header,wrapper) =
+ if !used
+ then
+ let label_pred = CTL.Pred (Lib_engine.Label(lv),CTL.Control) in
+ (ctl_and switch_header label_pred,
+ (function body -> quantify true [lv] body))
+ else (switch_header,function x -> x) in
+ wrapper
+ (end_control_structure b1fvs switch_header body
+ after_pred (Some(ctl_ex after_pred)) None aft after label guard)
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ let (hfvs,b1fvs,lbfvs,b2fvs,b3fvs,b4fvs,rbfvs) =
+ match
+ seq_fvs quantified
+ [Ast.get_fvs header;Ast.get_fvs lbrace;Ast.get_fvs decls;
+ Ast.get_fvs body;Ast.get_fvs rbrace]
+ with
+ [(hfvs,b1fvs);(lbfvs,b2fvs);(_,b3fvs);(_,b4fvs);(rbfvs,_)] ->
+ (hfvs,b1fvs,lbfvs,b2fvs,b3fvs,b4fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let (mhfvs,mb1fvs,mlbfvs,mb2fvs,mb3fvs,mb4fvs,mrbfvs) =
+ match
+ seq_fvs quantified
+ [Ast.get_mfvs header;Ast.get_mfvs lbrace;Ast.get_mfvs decls;
+ Ast.get_mfvs body;Ast.get_mfvs rbrace]
+ with
+ [(hfvs,b1fvs);(lbfvs,b2fvs);(_,b3fvs);(_,b4fvs);(rbfvs,_)] ->
+ (hfvs,b1fvs,lbfvs,b2fvs,b3fvs,b4fvs,rbfvs)
+ | _ -> failwith "not possible" in
+ let function_header = quantify guard hfvs (make_match header) in
+ let start_brace = quantify guard lbfvs (make_match lbrace) in
+ let stripped_rbrace =
+ match Ast.unwrap rbrace with
+ Ast.SeqEnd((data,info,_,_)) ->
+ Ast.rewrap rbrace(Ast.SeqEnd (Ast.make_mcode data))
+ | _ -> failwith "unexpected close brace" in
+ let end_brace =
+ let exit = CTL.Pred (Lib_engine.Exit,CTL.Control) in
+ let errorexit = CTL.Pred (Lib_engine.ErrorExit,CTL.Control) in
+ let fake_brace = CTL.Pred (Lib_engine.FakeBrace,CTL.Control) in
+ ctl_and
+ (quantify guard rbfvs (make_match rbrace))
+ (ctl_and
+ (* the following finds the beginning of the fake braces,
+ if there are any, not completely sure how this works.
+ sse the examples sw and return *)
+ (ctl_back_ex (ctl_not fake_brace))
+ (ctl_au (make_match stripped_rbrace) (ctl_or exit errorexit))) in
+ let new_quantified3 =
+ Common.union_set b1fvs
+ (Common.union_set b2fvs (Common.union_set b3fvs quantified)) in
+ let new_quantified4 = Common.union_set b4fvs new_quantified3 in
+ let new_mquantified3 =
+ Common.union_set mb1fvs
+ (Common.union_set mb2fvs
+ (Common.union_set mb3fvs minus_quantified)) in
+ let new_mquantified4 = Common.union_set mb4fvs new_mquantified3 in
+ let fn_nest =
+ match (Ast.undots decls,Ast.undots body,contains_modif rbrace) with
+ ([],[body],false) ->
+ (match Ast.unwrap body with
+ Ast.Nest(stmt_dots,[],multi,_,_) ->
+ if multi
+ then None (* not sure how to optimize this case *)
+ else Some (Common.Left stmt_dots)
+ | Ast.Dots(_,whencode,_,_) -> Some (Common.Right whencode)
+ | _ -> None)
+ | _ -> None in
+ let body_code =
+ match fn_nest with
+ Some (Common.Left stmt_dots) ->
+ (* special case for function header + body - header is unambiguous
+ and unique, so we can just look for the nested body anywhere
+ else in the CFG *)
+ CTL.AndAny
+ (CTL.FORWARD,guard_to_strict guard,start_brace,
+ statement_list stmt_dots
+ (* discards match on right brace, but don't need it *)
+ (Guard (make_seq_after end_brace after))
+ new_quantified4 new_mquantified4
+ None llabel slabel true guard)
+ | Some (Common.Right whencode) ->
+ (* try to be more efficient for the case where the body is just
+ ... Perhaps this is too much of a special case, but useful
+ for dropping a parameter and checking that it is never used. *)
+ make_seq
+ [start_brace;
+ match whencode with
+ [] -> CTL.True
+ | _ ->
+ let leftarg =
+ ctl_and
+ (ctl_not
+ (List.fold_left
+ (function prev ->
+ function
+ Ast.WhenAlways(s) -> prev
+ | Ast.WhenNot(sl) ->
+ let x =
+ statement_list sl Tail
+ new_quantified4 new_mquantified4
+ label llabel slabel true true in
+ ctl_or prev x
+ | Ast.WhenModifier(Ast.WhenAny) -> CTL.False
+ | Ast.WhenModifier(_) -> prev)
+ CTL.False whencode))
+ (List.fold_left
+ (function prev ->
+ function
+ Ast.WhenAlways(s) ->
+ let x =
+ statement s Tail
+ new_quantified4 new_mquantified4
+ label llabel slabel true in
+ ctl_and prev x
+ | Ast.WhenNot(sl) -> prev
+ | Ast.WhenModifier(Ast.WhenAny) -> CTL.True
+ | Ast.WhenModifier(_) -> prev)
+ CTL.True whencode) in
+ ctl_au leftarg (make_match stripped_rbrace)]
+ | None ->
+ make_seq
+ [start_brace;
+ quantify guard b3fvs
+ (statement_list decls
+ (After
+ (quantify guard b4fvs
+ (statement_list body
+ (After (make_seq_after end_brace after))
+ new_quantified4 new_mquantified4
+ None llabel slabel true guard)))
+ new_quantified3 new_mquantified3 None llabel slabel
+ false guard)] in
+ quantify guard b1fvs
+ (make_seq [function_header; quantify guard b2fvs body_code])
+ | Ast.Define(header,body) ->
+ let (hfvs,bfvs,bodyfvs) =
+ match seq_fvs quantified [Ast.get_fvs header;Ast.get_fvs body]
+ with
+ [(hfvs,b1fvs);(bodyfvs,_)] -> (hfvs,b1fvs,bodyfvs)
+ | _ -> failwith "not possible" in
+ let (mhfvs,mbfvs,mbodyfvs) =
+ match seq_fvs minus_quantified [Ast.get_mfvs header;Ast.get_mfvs body]
+ with
+ [(hfvs,b1fvs);(bodyfvs,_)] -> (hfvs,b1fvs,bodyfvs)
+ | _ -> failwith "not possible" in
+ let define_header = quantify guard hfvs (make_match header) in
+ let body_code =
+ statement_list body after
+ (Common.union_set bfvs quantified)
+ (Common.union_set mbfvs minus_quantified)
+ None llabel slabel true guard in
+ quantify guard bfvs (make_seq [define_header; body_code])
+ | Ast.OptStm(stm) ->
+ failwith "OptStm should have been compiled away\n"
+ | Ast.UniqueStm(stm) -> failwith "arities not yet supported"
+ | _ -> failwith "not supported" in
+ if guard or !dots_done
+ then term
+ else
+ do_between_dots stmt term after quantified minus_quantified
+ label llabel slabel guard
+
+(* term is the translation of stmt *)
+and do_between_dots stmt term after quantified minus_quantified
+ label llabel slabel guard =
+ match Ast.get_dots_bef_aft stmt with
+ Ast.AddingBetweenDots (brace_term,n)
+ | Ast.DroppingBetweenDots (brace_term,n) ->
+ let match_brace =
+ statement brace_term after quantified minus_quantified
+ label llabel slabel guard in
+ let v = Printf.sprintf "_r_%d" n in
+ let case1 = ctl_and CTL.NONSTRICT (CTL.Ref v) match_brace in
+ let case2 = ctl_and CTL.NONSTRICT (ctl_not (CTL.Ref v)) term in
+ CTL.Let
+ (v,ctl_or
+ (ctl_back_ex (ctl_or (truepred label) (inlooppred label)))
+ (ctl_back_ex (ctl_back_ex (falsepred label))),
+ ctl_or case1 case2)
+ | Ast.NoDots -> term
+
+(* un_process_bef_aft is because we don't want to do transformation in this
+ code, and thus don't case about braces before or after it *)
+and process_bef_aft quantified minus_quantified label llabel slabel guard =
+ function
+ Ast.WParen (re,n) ->
+ let paren_pred = CTL.Pred (Lib_engine.Paren n,CTL.Control) in
+ let s = guard_to_strict guard in
+ quantify true (get_unquantified quantified [n])
+ (ctl_and s (make_raw_match None guard re) paren_pred)
+ | Ast.Other s ->
+ statement s Tail quantified minus_quantified label llabel slabel guard
+ | Ast.Other_dots d ->
+ statement_list d Tail quantified minus_quantified
+ label llabel slabel true guard
+
+(* --------------------------------------------------------------------- *)
+(* cleanup: convert AX to EX for pdots.
+Concretely: AX(A[...] & E[...]) becomes AX(A[...]) & EX(E[...])
+This is what we wanted in the first place, but it wasn't possible to make
+because the AX and its argument are not created in the same place.
+Rather clunky... *)
+(* also cleanup XX, which is a marker for the case where the programmer
+specifies to change the quantifier on .... Assumed to only occur after one AX
+or EX, or at top level. *)
+
+let rec cleanup c =
+ let c = match c with CTL.XX(c) -> c | _ -> c in
+ match c with
+ CTL.False -> CTL.False
+ | CTL.True -> CTL.True
+ | CTL.Pred(p) -> CTL.Pred(p)
+ | CTL.Not(phi) -> CTL.Not(cleanup phi)
+ | CTL.Exists(keep,v,phi) -> CTL.Exists(keep,v,cleanup phi)
+ | CTL.AndAny(dir,s,phi1,phi2) ->
+ CTL.AndAny(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.HackForStmt(dir,s,phi1,phi2) ->
+ CTL.HackForStmt(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.And(s,phi1,phi2) -> CTL.And(s,cleanup phi1,cleanup phi2)
+ | CTL.Or(phi1,phi2) -> CTL.Or(cleanup phi1,cleanup phi2)
+ | CTL.SeqOr(phi1,phi2) -> CTL.SeqOr(cleanup phi1,cleanup phi2)
+ | CTL.Implies(phi1,phi2) -> CTL.Implies(cleanup phi1,cleanup phi2)
+ | CTL.AF(dir,s,phi1) -> CTL.AF(dir,s,cleanup phi1)
+ | CTL.AX(CTL.FORWARD,s,
+ CTL.Let(v1,e1,
+ CTL.And(CTL.NONSTRICT,CTL.AU(CTL.FORWARD,s2,e2,e3),
+ CTL.EU(CTL.FORWARD,e4,e5)))) ->
+ CTL.Let(v1,e1,
+ CTL.And(CTL.NONSTRICT,
+ CTL.AX(CTL.FORWARD,s,CTL.AU(CTL.FORWARD,s2,e2,e3)),
+ CTL.EX(CTL.FORWARD,CTL.EU(CTL.FORWARD,e4,e5))))
+ | CTL.AX(dir,s,CTL.XX(phi)) -> CTL.EX(dir,cleanup phi)
+ | CTL.EX(dir,CTL.XX((CTL.AU(_,s,_,_)) as phi)) ->
+ CTL.AX(dir,s,cleanup phi)
+ | CTL.XX(phi) -> failwith "bad XX"
+ | CTL.AX(dir,s,phi1) -> CTL.AX(dir,s,cleanup phi1)
+ | CTL.AG(dir,s,phi1) -> CTL.AG(dir,s,cleanup phi1)
+ | CTL.EF(dir,phi1) -> CTL.EF(dir,cleanup phi1)
+ | CTL.EX(dir,phi1) -> CTL.EX(dir,cleanup phi1)
+ | CTL.EG(dir,phi1) -> CTL.EG(dir,cleanup phi1)
+ | CTL.AW(dir,s,phi1,phi2) -> CTL.AW(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.AU(dir,s,phi1,phi2) -> CTL.AU(dir,s,cleanup phi1,cleanup phi2)
+ | CTL.EU(dir,phi1,phi2) -> CTL.EU(dir,cleanup phi1,cleanup phi2)
+ | CTL.Let (x,phi1,phi2) -> CTL.Let (x,cleanup phi1,cleanup phi2)
+ | CTL.LetR (dir,x,phi1,phi2) -> CTL.LetR (dir,x,cleanup phi1,cleanup phi2)
+ | CTL.Ref(s) -> CTL.Ref(s)
+ | CTL.Uncheck(phi1) -> CTL.Uncheck(cleanup phi1)
+ | CTL.InnerAnd(phi1) -> CTL.InnerAnd(cleanup phi1)
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+
+let top_level name (ua,pos) t =
+ let ua = List.filter (function (nm,_) -> nm = name) ua in
+ used_after := ua;
+ saved := Ast.get_saved t;
+ let quantified = Common.minus_set ua pos in
+ quantify false quantified
+ (match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) -> failwith "not supported fileinfo"
+ | Ast.DECL(stmt) ->
+ let unopt = elim_opt.V.rebuilder_statement stmt in
+ let unopt = preprocess_dots_e unopt in
+ cleanup(statement unopt VeryEnd quantified [] None None None false)
+ | Ast.CODE(stmt_dots) ->
+ let unopt = elim_opt.V.rebuilder_statement_dots stmt_dots in
+ let unopt = preprocess_dots unopt in
+ let starts_with_dots =
+ match Ast.undots stmt_dots with
+ d::ds ->
+ (match Ast.unwrap d with
+ Ast.Dots(_,_,_,_) | Ast.Circles(_,_,_,_)
+ | Ast.Stars(_,_,_,_) -> true
+ | _ -> false)
+ | _ -> false in
+ let starts_with_brace =
+ match Ast.undots stmt_dots with
+ d::ds ->
+ (match Ast.unwrap d with
+ Ast.Seq(_) -> true
+ | _ -> false)
+ | _ -> false in
+ let res =
+ statement_list unopt VeryEnd quantified [] None None None
+ false false in
+ cleanup
+ (if starts_with_dots
+ then
+ (* EX because there is a loop on enter/top *)
+ ctl_and CTL.NONSTRICT (toppred None) (ctl_ex res)
+ else if starts_with_brace
+ then
+ ctl_and CTL.NONSTRICT
+ (ctl_not(CTL.EX(CTL.BACKWARD,(funpred None)))) res
+ else res)
+ | Ast.ERRORWORDS(exps) -> failwith "not supported errorwords")
+
+(* --------------------------------------------------------------------- *)
+(* Entry points *)
+
+let asttoctlz (name,(_,_,exists_flag),l) used_after positions =
+ letctr := 0;
+ labelctr := 0;
+ (match exists_flag with
+ Ast.Exists -> exists := Exists
+ | Ast.Forall -> exists := Forall
+ | Ast.ReverseForall -> exists := ReverseForall
+ | Ast.Undetermined ->
+ exists := if !Flag.sgrep_mode2 then Exists else Forall);
+
+ let (l,used_after) =
+ List.split
+ (List.filter
+ (function (t,_) ->
+ match Ast.unwrap t with Ast.ERRORWORDS(exps) -> false | _ -> true)
+ (List.combine l (List.combine used_after positions))) in
+ let res = List.map2 (top_level name) used_after l in
+ exists := Forall;
+ res
+
+let asttoctl r used_after positions =
+ match r with
+ Ast.ScriptRule _ -> []
+ | Ast.CocciRule (a,b,c,_) -> asttoctlz (a,b,c) used_after positions
+
+let pp_cocci_predicate (pred,modif) =
+ Pretty_print_engine.pp_predicate pred
+
+let cocci_predicate_to_string (pred,modif) =
+ Pretty_print_engine.predicate_to_string pred
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+
+(* Just to warn me when there is some news in the types in
+ * ast_cocci.ml or even ast_c.ml, so that I can then adjust my code in
+ * pattern.ml or transformation.ml.
+ *
+ * For the moment I do it only for myself (pad), that is I check only
+ * for news in ast_cocci.ml, because I already know when I add stuff in
+ * my code in ast_c.ml or control_flow_c.ml. *)
+
+module A = Ast_cocci
+module B = Ast_c
+module F = Control_flow_c
+
+(* dependencies_to_adjust: pattern.ml, transformaton.ml *)
+
+let dumb_astcocci_rule_elem = function
+ | A.MetaRuleElem _ -> ()
+ | A.MetaStmt (ida,_,_,_) -> ()
+ | A.MetaStmtList _ -> ()
+ | A.Exp expr -> ()
+ | A.TopExp expr -> ()
+ | A.Ty ty -> ()
+ | A.FunHeader (bef,allminus, fninfo, ida, _, paramsa, _) -> ()
+ | A.Decl (bef,allminus,decla) -> ()
+ | A.SeqStart _ -> ()
+ | A.SeqEnd _ -> ()
+ | A.ExprStatement (ea, _) -> ()
+ | A.IfHeader (_,_, ea, _) -> ()
+ | A.Else _ -> ()
+ | A.WhileHeader (_, _, ea, _) -> ()
+ | A.DoHeader _ -> ()
+ | A.WhileTail (_,_,ea,_,_) -> ()
+ | A.ForHeader (_, _, ea1opt, _, ea2opt, _, ea3opt, _) -> ()
+ | A.IteratorHeader (ia1, ia2, ea, ia3) -> ()
+ | A.SwitchHeader _ -> ()
+ | A.Break _ -> ()
+ | A.Continue _ -> ()
+ | A.Label _ -> ()
+ | A.Goto(_,_,_) -> ()
+ | A.Return _ -> ()
+ | A.ReturnExpr (_, ea, _) -> ()
+ | A.DefineHeader _ -> ()
+ | A.Include _ -> ()
+ | A.Default _ -> ()
+ | A.Case _ -> ()
+ | A.DisjRuleElem _ -> failwith "not possible - compiled away in asttoctl"
+
+let dumb_astcocci_decl = function
+ | A.UnInit (stg, typa, sa, _) -> ()
+ | A.Init (stg, typa, sa, _, expa, _) -> ()
+ | A.TyDecl (typa, _) -> ()
+ | A.MacroDecl(fn, _, eas, _, _) -> ()
+ | A.Ddots(dots,whencode) -> ()
+ | A.MetaDecl _ -> ()
+ | A.Typedef(d,ty1,ty2,pv) -> ()
+ | A.DisjDecl xs -> ()
+ | A.OptDecl _ | A.UniqueDecl _ -> ()
+
+let dumb_astcocci_initialiser = function
+ A.Init(stg,ty,id,eq,ini,sem) -> ()
+ | A.UnInit(stg,ty,id,sem) -> ()
+ | A.MacroDecl(fn, _, eas, _, _) -> ()
+ | A.TyDecl(ty,sem) -> ()
+ | A.Typedef(d,ty1,ty2,pv) -> ()
+ | A.DisjDecl(decls) -> ()
+ | A.Ddots(dots,whencode) -> ()
+ | A.MetaDecl(name,_,_) -> ()
+ | A.OptDecl(decl) -> ()
+ | A.UniqueDecl(decl) -> ()
+
+let dumb_astcocci_expr = function
+ | A.MetaExpr (ida,_,_, opttypa, _, _) -> ()
+ | A.Edots (_,_) -> ()
+ | A.MetaErr _ -> ()
+ | A.Ident ida -> ()
+ | A.Constant (A.String sa,_,_,_) -> ()
+ | A.Constant (A.Char sa,_,_,_) -> ()
+ | A.Constant (A.Int sa,_,_,_) -> ()
+ | A.Constant (A.Float sa,_,_,_) -> ()
+ | A.FunCall (ea1, _, eas, _) -> ()
+ | A.Assignment (ea1, opa, ea2, _) -> ()
+ | A.CondExpr (ea1,_,ea2opt,_,ea3) -> ()
+ | A.Postfix (ea, opa) -> ()
+ | A.Infix (ea, opa) -> ()
+ | A.Unary (ea, opa) -> ()
+ | A.Binary (ea1, opa, ea2) -> ()
+ | A.Nested (ea1, opa, ea2) -> ()
+ | A.ArrayAccess (ea1, _, ea2, _) -> ()
+ | A.RecordAccess (ea, _, ida) -> ()
+ | A.RecordPtAccess (ea, _, ida) -> ()
+ | A.Cast (_, typa, _, ea) -> ()
+ | A.SizeOfExpr (_, ea) -> ()
+ | A.SizeOfType (_, _, typa, _) -> ()
+ | A.TypeExp (typa) -> ()
+ | A.Paren (_, ea, _) -> ()
+ | A.NestExpr _ -> ()
+ | A.MetaExprList _ -> ()
+ | A.EComma _ -> ()
+ | A.Ecircles _ -> ()
+ | A.Estars _ -> ()
+ | A.DisjExpr eas -> ()
+ | A.UniqueExp _ -> ()
+ | A.OptExp _ -> ()
+
+let dumb_astcocci_fulltype = function
+ A.Type(cv,ty) -> ()
+ | A.DisjType(types) -> ()
+ | A.OptType(ty) -> ()
+ | A.UniqueType(ty) -> ()
+
+let dumb_astcocci_type = function
+ | A.MetaType(ida,_,_) -> ()
+ | A.BaseType (basea, signaopt) -> ()
+ | A.ImplicitInt (signa) -> ()
+ | A.Pointer (typa, _) -> ()
+ | A.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> ()
+ | A.FunctionType _ -> ()
+ | A.Array (typa, _, eaopt, _) -> ()
+ | A.StructUnionName(sa, sua) -> ()
+ | A.StructUnionDef(ty, lb, decls, rb) -> ()
+ | A.TypeName sa -> ()
+
+
+(* ------------------------------------------------------------------------- *)
+(* for C *)
+(*
+ | (Ident (_) | Constant _ | FunCall (_,_) | CondExpr (_,_,_)
+ | Sequence (_,_)
+ | Assignment (_,_,_)
+ | Postfix (_,_) | Infix (_,_) | Unary (_,_) | Binary (_,_,_)
+ | ArrayAccess (_,_) | RecordAccess (_,_) | RecordPtAccess (_,_)
+ | SizeOfExpr (_) | SizeOfType (_) | Cast (_,_)
+ | StatementExpr (_) | Constructor
+ | ParenExpr (_) | MacroCall (_) | MacroCall2 (_)
+ ),_ ->
+
+ | ( Labeled (Label (_,_)) | Labeled (Case (_,_))
+ | Labeled (CaseRange (_,_,_)) | Labeled (Default _)
+ | Compound _ | ExprStatement _
+ | Selection (If (_, _, _)) | Selection (Switch (_, _))
+ | Iteration (While (_, _)) | Iteration (DoWhile (_, _))
+ | Iteration (For ((_,_), (_,_), (_, _), _))
+ | Jump (Goto _) | Jump ((Continue|Break|Return)) | Jump (ReturnExpr _)
+ | Decl _ | Asm | Selection (IfCpp (_,_))
+ ), _ ->
+*)
+
+(* for control flow nodes
+
+ | ( F.ExprStatement (_, _)
+ | F.IfHeader (_, _) | F.SwitchHeader (_, _)
+ | F.WhileHeader (_, _) | (* F.DoHeader (_, _) | *) F.DoWhileTail (_, _)
+ | F.ForHeader (_, _)
+ | F.Return (_, _) | F.ReturnExpr (_, _)
+ (* no counter part in cocci *)
+ | F.Label (_, _)
+ | F.Case (_,_) | (* F.CaseRange (_, _) | *) F.Default (_, _)
+ | F.Goto (_, _) | F.Continue (_, _) | F.Break (_, _)
+ ) -> raise Impossible
+
+*)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Common
+
+module A = Ast_cocci
+module B = Ast_c
+
+module F = Control_flow_c
+
+(*****************************************************************************)
+(* Wrappers *)
+(*****************************************************************************)
+
+(*****************************************************************************)
+(* Helpers *)
+(*****************************************************************************)
+
+type sequence = Ordered | Unordered
+
+let seqstyle eas =
+ match A.unwrap eas with
+ | A.DOTS _ -> Ordered
+ | A.CIRCLES _ -> Unordered
+ | A.STARS _ -> failwith "not handling stars"
+
+let (redots : 'a A.dots -> 'a list -> 'a A.dots)=fun eas easundots ->
+ A.rewrap eas (
+ match A.unwrap eas with
+ | A.DOTS _ -> A.DOTS easundots
+ | A.CIRCLES _ -> A.CIRCLES easundots
+ | A.STARS _ -> A.STARS easundots
+ )
+
+
+let (need_unordered_initialisers : B.initialiser B.wrap2 list -> bool) =
+ fun ibs ->
+ ibs +> List.exists (fun (ib, icomma) ->
+ match B.unwrap ib with
+ | B.InitDesignators _
+ | B.InitFieldOld _
+ | B.InitIndexOld _
+ -> true
+ | B.InitExpr _
+ | B.InitList _
+ -> false
+ )
+
+(* For the #include <linux/...> in the .cocci, need to find where is
+ * the '+' attached to this element, to later find the first concrete
+ * #include <linux/xxx.h> or last one in the serie of #includes in the
+ * .c.
+ *)
+type include_requirement =
+ | IncludeMcodeBefore
+ | IncludeMcodeAfter
+ | IncludeNothing
+
+
+
+(* todo? put in semantic_c.ml *)
+type info_ident =
+ | Function
+ | LocalFunction (* entails Function *)
+ | DontKnow
+
+
+let term mc = A.unwrap_mcode mc
+let mcodekind mc = A.get_mcodekind mc
+
+
+let mcode_contain_plus = function
+ | A.CONTEXT (_,A.NOTHING) -> false
+ | A.CONTEXT _ -> true
+ | A.MINUS (_,[]) -> false
+ | A.MINUS (_,x::xs) -> true
+ | A.PLUS -> raise Impossible
+
+let mcode_simple_minus = function
+ | A.MINUS (_,[]) -> true
+ | _ -> false
+
+
+(* In transformation.ml sometime I build some mcodekind myself and
+ * julia has put None for the pos. But there is no possible raise
+ * NoMatch in those cases because it is for the minusall trick or for
+ * the distribute, so either have to build those pos, in fact a range,
+ * because for the distribute have to erase a fullType with one
+ * mcodekind, or add an argument to tag_with_mck such as "safe" that
+ * don't do the check_pos. Hence this DontCarePos constructor. *)
+
+let minusizer =
+ ("fake","fake"),
+ {A.line = 0; column =0; A.strbef=[]; A.straft=[];},
+ (A.MINUS(A.DontCarePos, [])),
+ A.NoMetaPos
+
+let generalize_mcode ia =
+ let (s1, i, mck, pos) = ia in
+ let new_mck =
+ match mck with
+ | A.PLUS -> raise Impossible
+ | A.CONTEXT (A.NoPos,x) ->
+ A.CONTEXT (A.DontCarePos,x)
+ | A.MINUS (A.NoPos,x) ->
+ A.MINUS (A.DontCarePos,x)
+ | _ -> raise Impossible in
+ (s1, i, new_mck, pos)
+
+
+
+(*---------------------------------------------------------------------------*)
+
+(* 0x0 is equivalent to 0, value format isomorphism *)
+let equal_c_int s1 s2 =
+ try
+ int_of_string s1 = int_of_string s2
+ with Failure("int_of_string") ->
+ s1 =$= s2
+
+
+
+(*---------------------------------------------------------------------------*)
+(* Normally A should reuse some types of Ast_c, so those
+ * functions should not exist.
+ *
+ * update: but now Ast_c depends on A, so can't make too
+ * A depends on Ast_c, so have to stay with those equal_xxx
+ * functions.
+ *)
+
+let equal_unaryOp a b =
+ match a, b with
+ | A.GetRef , B.GetRef -> true
+ | A.DeRef , B.DeRef -> true
+ | A.UnPlus , B.UnPlus -> true
+ | A.UnMinus , B.UnMinus -> true
+ | A.Tilde , B.Tilde -> true
+ | A.Not , B.Not -> true
+ | _, _ -> false
+
+let equal_arithOp a b =
+ match a, b with
+ | A.Plus , B.Plus -> true
+ | A.Minus , B.Minus -> true
+ | A.Mul , B.Mul -> true
+ | A.Div , B.Div -> true
+ | A.Mod , B.Mod -> true
+ | A.DecLeft , B.DecLeft -> true
+ | A.DecRight , B.DecRight -> true
+ | A.And , B.And -> true
+ | A.Or , B.Or -> true
+ | A.Xor , B.Xor -> true
+ | _ , _ -> false
+
+let equal_logicalOp a b =
+ match a, b with
+ | A.Inf , B.Inf -> true
+ | A.Sup , B.Sup -> true
+ | A.InfEq , B.InfEq -> true
+ | A.SupEq , B.SupEq -> true
+ | A.Eq , B.Eq -> true
+ | A.NotEq , B.NotEq -> true
+ | A.AndLog , B.AndLog -> true
+ | A.OrLog , B.OrLog -> true
+ | _ , _ -> false
+
+let equal_assignOp a b =
+ match a, b with
+ | A.SimpleAssign, B.SimpleAssign -> true
+ | A.OpAssign a, B.OpAssign b -> equal_arithOp a b
+ | _ -> false
+
+let equal_fixOp a b =
+ match a, b with
+ | A.Dec, B.Dec -> true
+ | A.Inc, B.Inc -> true
+ | _ -> false
+
+let equal_binaryOp a b =
+ match a, b with
+ | A.Arith a, B.Arith b -> equal_arithOp a b
+ | A.Logical a, B.Logical b -> equal_logicalOp a b
+ | _ -> false
+
+let equal_structUnion a b =
+ match a, b with
+ | A.Struct, B.Struct -> true
+ | A.Union, B.Union -> true
+ | _, _ -> false
+
+let equal_sign a b =
+ match a, b with
+ | A.Signed, B.Signed -> true
+ | A.Unsigned, B.UnSigned -> true
+ | _, _ -> false
+
+let equal_storage a b =
+ match a, b with
+ | A.Static , B.Sto B.Static
+ | A.Auto , B.Sto B.Auto
+ | A.Register , B.Sto B.Register
+ | A.Extern , B.Sto B.Extern
+ -> true
+ | _ -> false
+
+(*---------------------------------------------------------------------------*)
+
+let equal_metavarval valu valu' =
+ match valu, valu' with
+ | Ast_c.MetaIdVal a, Ast_c.MetaIdVal b -> a =$= b
+ | Ast_c.MetaFuncVal a, Ast_c.MetaFuncVal b -> a =$= b
+ | Ast_c.MetaLocalFuncVal a, Ast_c.MetaLocalFuncVal b ->
+ (* do something more ? *)
+ a =$= b
+
+ (* al_expr before comparing !!! and accept when they match.
+ * Note that here we have Astc._expression, so it is a match
+ * modulo isomorphism (there is no metavariable involved here,
+ * just isomorphisms). => TODO call isomorphism_c_c instead of
+ * =*=. Maybe would be easier to transform ast_c in ast_cocci
+ * and call the iso engine of julia. *)
+ | Ast_c.MetaExprVal a, Ast_c.MetaExprVal b ->
+ Lib_parsing_c.al_expr a =*= Lib_parsing_c.al_expr b
+ | Ast_c.MetaExprListVal a, Ast_c.MetaExprListVal b ->
+ Lib_parsing_c.al_arguments a =*= Lib_parsing_c.al_arguments b
+
+ | Ast_c.MetaStmtVal a, Ast_c.MetaStmtVal b ->
+ Lib_parsing_c.al_statement a =*= Lib_parsing_c.al_statement b
+ | Ast_c.MetaTypeVal a, Ast_c.MetaTypeVal b ->
+ (* old: Lib_parsing_c.al_type a =*= Lib_parsing_c.al_type b *)
+ C_vs_c.eq_type a b
+
+ | Ast_c.MetaListlenVal a, Ast_c.MetaListlenVal b -> a =|= b
+
+ | Ast_c.MetaParamVal a, Ast_c.MetaParamVal b ->
+ Lib_parsing_c.al_param a =*= Lib_parsing_c.al_param b
+ | Ast_c.MetaParamListVal a, Ast_c.MetaParamListVal b ->
+ Lib_parsing_c.al_params a =*= Lib_parsing_c.al_params b
+
+ | Ast_c.MetaPosVal (posa1,posa2), Ast_c.MetaPosVal (posb1,posb2) ->
+ Ast_cocci.equal_pos posa1 posb1 && Ast_cocci.equal_pos posa2 posb2
+
+ | Ast_c.MetaPosValList l1, Ast_c.MetaPosValList l2 ->
+ List.exists
+ (function (fla,posa1,posa2) ->
+ List.exists
+ (function (flb,posb1,posb2) ->
+ fla = flb &&
+ Ast_c.equal_posl posa1 posb1 && Ast_c.equal_posl posa2 posb2)
+ l2)
+ l1
+ | _ -> raise Impossible
+
+
+
+(*---------------------------------------------------------------------------*)
+(* could put in ast_c.ml, next to the split/unsplit_comma *)
+let split_signb_baseb_ii (baseb, ii) =
+ let iis = ii +> List.map (fun info -> (B.str_of_info info), info) in
+ match baseb, iis with
+
+ | B.Void, ["void",i1] -> None, [i1]
+
+ | B.FloatType (B.CFloat),["float",i1] -> None, [i1]
+ | B.FloatType (B.CDouble),["double",i1] -> None, [i1]
+ | B.FloatType (B.CLongDouble),["long",i1;"double",i2] -> None,[i1;i2]
+
+ | B.IntType (B.CChar), ["char",i1] -> None, [i1]
+
+
+ | B.IntType (B.Si (sign, base)), xs ->
+ (match sign, base, xs with
+ | B.Signed, B.CChar2, ["signed",i1;"char",i2] ->
+ Some (B.Signed, i1), [i2]
+ | B.UnSigned, B.CChar2, ["unsigned",i1;"char",i2] ->
+ Some (B.UnSigned, i1), [i2]
+
+ | B.Signed, B.CShort, ["short",i1] ->
+ None, [i1]
+ | B.Signed, B.CShort, ["signed",i1;"short",i2] ->
+ Some (B.Signed, i1), [i2]
+ | B.UnSigned, B.CShort, ["unsigned",i1;"short",i2] ->
+ Some (B.UnSigned, i1), [i2]
+ | B.Signed, B.CShort, ["short",i1;"int",i2] ->
+ None, [i1;i2]
+
+ | B.Signed, B.CInt, ["int",i1] ->
+ None, [i1]
+ | B.Signed, B.CInt, ["signed",i1;"int",i2] ->
+ Some (B.Signed, i1), [i2]
+ | B.UnSigned, B.CInt, ["unsigned",i1;"int",i2] ->
+ Some (B.UnSigned, i1), [i2]
+
+ | B.Signed, B.CInt, ["signed",i1;] ->
+ Some (B.Signed, i1), []
+ | B.UnSigned, B.CInt, ["unsigned",i1;] ->
+ Some (B.UnSigned, i1), []
+
+ | B.Signed, B.CLong, ["long",i1] ->
+ None, [i1]
+ | B.Signed, B.CLong, ["long",i1;"int",i2] ->
+ None, [i1;i2]
+ | B.Signed, B.CLong, ["signed",i1;"long",i2] ->
+ Some (B.Signed, i1), [i2]
+ | B.UnSigned, B.CLong, ["unsigned",i1;"long",i2] ->
+ Some (B.UnSigned, i1), [i2]
+
+ | B.Signed, B.CLongLong, ["long",i1;"long",i2] -> None, [i1;i2]
+ | B.Signed, B.CLongLong, ["signed",i1;"long",i2;"long",i3] ->
+ Some (B.Signed, i1), [i2;i3]
+ | B.UnSigned, B.CLongLong, ["unsigned",i1;"long",i2;"long",i3] ->
+ Some (B.UnSigned, i1), [i2;i3]
+
+
+ | B.UnSigned, B.CShort, ["unsigned",i1;"short",i2; "int", i3] ->
+ Some (B.UnSigned, i1), [i2;i3]
+
+
+
+ | _ -> failwith "strange type1, maybe because of weird order"
+ )
+ | _ -> failwith "strange type2, maybe because of weird order"
+
+(*---------------------------------------------------------------------------*)
+
+let rec unsplit_icomma xs =
+ match xs with
+ | [] -> []
+ | x::y::xs ->
+ (match A.unwrap y with
+ | A.IComma mcode ->
+ (x, y)::unsplit_icomma xs
+ | _ -> failwith "wrong ast_cocci in initializer"
+ )
+ | _ ->
+ failwith ("wrong ast_cocci in initializer, should have pair " ^
+ "number of Icomma")
+
+
+
+let resplit_initialiser ibs iicomma =
+ match iicomma, ibs with
+ | [], [] -> []
+ | [], _ ->
+ failwith "should have a iicomma, do you generate fakeInfo in parser?"
+ | _, [] ->
+ failwith "shouldn't have a iicomma"
+ | [iicomma], x::xs ->
+ let elems = List.map fst (x::xs) in
+ let commas = List.map snd (x::xs) +> List.flatten in
+ let commas = commas @ [iicomma] in
+ zip elems commas
+ | _ -> raise Impossible
+
+
+
+let rec split_icomma xs =
+ match xs with
+ | [] -> []
+ | (x,y)::xs -> x::y::split_icomma xs
+
+let rec unsplit_initialiser ibs_unsplit =
+ match ibs_unsplit with
+ | [] -> [], [] (* empty iicomma *)
+ | (x, commax)::xs ->
+ let (xs, lastcomma) = unsplit_initialiser_bis commax xs in
+ (x, [])::xs, lastcomma
+
+and unsplit_initialiser_bis comma_before = function
+ | [] -> [], [comma_before]
+ | (x, commax)::xs ->
+ let (xs, lastcomma) = unsplit_initialiser_bis commax xs in
+ (x, [comma_before])::xs, lastcomma
+
+
+
+
+(*---------------------------------------------------------------------------*)
+(* coupling: same in type_annotater_c.ml *)
+let structdef_to_struct_name ty =
+ match ty with
+ | qu, (B.StructUnion (su, sopt, fields), iis) ->
+ (match sopt,iis with
+ | Some s , [i1;i2;i3;i4] ->
+ qu, (B.StructUnionName (su, s), [i1;i2])
+ | None, _ ->
+ ty
+
+ | x -> raise Impossible
+ )
+ | _ -> raise Impossible
+
+(*---------------------------------------------------------------------------*)
+let initialisation_to_affectation decl =
+ match decl with
+ | B.MacroDecl _ -> F.Decl decl
+ | B.DeclList (xs, iis) ->
+
+ (* todo?: should not do that if the variable is an array cos
+ * will have x[] = , mais de toute facon ca sera pas un InitExp
+ *)
+ (match xs with
+ | [] -> raise Impossible
+ | [x] ->
+ let ((var, returnType, storage, local),iisep) = x in
+
+ (match var with
+ | Some ((s, ini), iis::iini) ->
+ (match ini with
+ | Some (B.InitExpr e, ii_empty2) ->
+ let local =
+ match local with
+ Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
+ | Ast_c.LocalDecl -> Ast_c.LocalVar (iis.Ast_c.pinfo) in
+
+ let typ =
+ ref (Some ((Lib_parsing_c.al_type returnType),local),
+ Ast_c.NotTest) in
+ let id = (B.Ident s, typ),[iis] in
+ F.DefineExpr
+ ((B.Assignment (id, B.SimpleAssign, e),
+ Ast_c.noType()), iini)
+ | _ -> F.Decl decl
+ )
+ | _ -> F.Decl decl
+ )
+ | x::xs ->
+ pr2_once "TODO: initialisation_to_affectation for multi vars";
+ (* todo? do a fold_left and generate 'x = a, y = b' etc, use
+ * the Sequence expression operator of C and make an
+ * ExprStatement from that.
+ *)
+ F.Decl decl
+ )
+
+
+
+
+
+(*****************************************************************************)
+(* Functor parameter combinators *)
+(*****************************************************************************)
+(* monad like stuff
+ * src: papers on parser combinators in haskell (cf a pearl by meijer in ICFP)
+ *
+ * version0: was not tagging the SP, so just tag the C
+ * val (>>=):
+ * (tin -> 'c tout) -> ('c -> (tin -> 'b tout)) -> (tin -> 'b tout)
+ * val return : 'b -> tin -> 'b tout
+ * val fail : tin -> 'b tout
+ *
+ * version1: now also tag the SP so return a ('a * 'b)
+ *)
+
+type mode = PatternMode | TransformMode
+
+module type PARAM =
+ sig
+ type tin
+ type 'x tout
+
+
+ type ('a, 'b) matcher = 'a -> 'b -> tin -> ('a * 'b) tout
+
+ val mode : mode
+
+ val (>>=):
+ (tin -> ('a * 'b) tout) ->
+ ('a -> 'b -> (tin -> ('c * 'd) tout)) ->
+ (tin -> ('c * 'd) tout)
+
+ val return : ('a * 'b) -> tin -> ('a *'b) tout
+ val fail : tin -> ('a * 'b) tout
+
+ val (>||>) :
+ (tin -> 'x tout) ->
+ (tin -> 'x tout) ->
+ (tin -> 'x tout)
+
+ val (>|+|>) :
+ (tin -> 'x tout) ->
+ (tin -> 'x tout) ->
+ (tin -> 'x tout)
+
+ val (>&&>) : (tin -> bool) -> (tin -> 'x tout) -> (tin -> 'x tout)
+
+ val tokenf : ('a A.mcode, B.info) matcher
+ val tokenf_mck : (A.mcodekind, B.info) matcher
+
+ val distrf_e :
+ (A.meta_name A.mcode, B.expression) matcher
+ val distrf_args :
+ (A.meta_name A.mcode, (Ast_c.argument, Ast_c.il) either list) matcher
+ val distrf_type :
+ (A.meta_name A.mcode, Ast_c.fullType) matcher
+ val distrf_params :
+ (A.meta_name A.mcode,
+ (Ast_c.parameterType, Ast_c.il) either list) matcher
+ val distrf_param :
+ (A.meta_name A.mcode, Ast_c.parameterType) matcher
+ val distrf_ini :
+ (A.meta_name A.mcode, Ast_c.initialiser) matcher
+ val distrf_node :
+ (A.meta_name A.mcode, Control_flow_c.node) matcher
+
+ val distrf_define_params :
+ (A.meta_name A.mcode, (string Ast_c.wrap, Ast_c.il) either list)
+ matcher
+
+ val distrf_struct_fields :
+ (A.meta_name A.mcode, B.field B.wrap list) matcher
+
+ val distrf_cst :
+ (A.meta_name A.mcode, (B.constant, string) either B.wrap) matcher
+
+ val cocciExp :
+ (A.expression, B.expression) matcher -> (A.expression, F.node) matcher
+
+ val cocciExpExp :
+ (A.expression, B.expression) matcher ->
+ (A.expression, B.expression) matcher
+
+ val cocciTy :
+ (A.fullType, B.fullType) matcher -> (A.fullType, F.node) matcher
+
+ val envf :
+ A.keep_binding -> A.inherited ->
+ A.meta_name A.mcode * Ast_c.metavar_binding_kind *
+ (unit -> Common.filename * Ast_c.posl * Ast_c.posl) ->
+ (unit -> tin -> 'x tout) -> (tin -> 'x tout)
+
+ val check_constraints :
+ ('a, 'b) matcher -> 'a list -> 'b ->
+ (unit -> tin -> 'x tout) -> (tin -> 'x tout)
+
+ val all_bound : A.meta_name list -> (tin -> bool)
+
+ val optional_storage_flag : (bool -> tin -> 'x tout) -> (tin -> 'x tout)
+ val optional_qualifier_flag : (bool -> tin -> 'x tout) -> (tin -> 'x tout)
+ val value_format_flag: (bool -> tin -> 'x tout) -> (tin -> 'x tout)
+
+
+ end
+
+(*****************************************************************************)
+(* Functor code, "Cocci vs C" *)
+(*****************************************************************************)
+
+module COCCI_VS_C =
+ functor (X : PARAM) ->
+struct
+
+type ('a, 'b) matcher = 'a -> 'b -> X.tin -> ('a * 'b) X.tout
+
+let (>>=) = X.(>>=)
+let return = X.return
+let fail = X.fail
+
+let (>||>) = X.(>||>)
+let (>|+|>) = X.(>|+|>)
+let (>&&>) = X.(>&&>)
+
+let tokenf = X.tokenf
+
+(* should be raise Impossible when called from transformation.ml *)
+let fail2 () =
+ match X.mode with
+ | PatternMode -> fail
+ | TransformMode -> raise Impossible
+
+
+let (option: ('a,'b) matcher -> ('a option,'b option) matcher)= fun f t1 t2 ->
+ match (t1,t2) with
+ | (Some t1, Some t2) ->
+ f t1 t2 >>= (fun t1 t2 ->
+ return (Some t1, Some t2)
+ )
+ | (None, None) -> return (None, None)
+ | _ -> fail
+
+(* Dots are sometimes used as metavariables, since like metavariables they
+can match other things. But they no longer have the same type. Perhaps these
+functions could be avoided by introducing an appropriate level of polymorphism,
+but I don't know how to declare polymorphism across functors *)
+let dots2metavar (_,info,mcodekind,pos) = (("","..."),info,mcodekind,pos)
+let metavar2dots (_,info,mcodekind,pos) = ("...",info,mcodekind,pos)
+
+(*---------------------------------------------------------------------------*)
+(* toc:
+ * - expression
+ * - ident
+ * - arguments
+ * - parameters
+ * - declaration
+ * - initialisers
+ * - type
+ * - node
+ *)
+
+(*---------------------------------------------------------------------------*)
+let rec (expression: (A.expression, Ast_c.expression) matcher) =
+ fun ea eb ->
+ X.all_bound (A.get_inherited ea) >&&>
+ let wa x = A.rewrap ea x in
+ match A.unwrap ea, eb with
+
+ (* general case: a MetaExpr can match everything *)
+ | A.MetaExpr (ida,constraints,keep,opttypa,form,inherited),
+ (((expr, opttypb), ii) as expb) ->
+
+ (* old: before have a MetaConst. Now we factorize and use 'form' to
+ * differentiate between different cases *)
+ let rec matches_id = function
+ B.Ident(c) -> true
+ | B.Cast(ty,e) -> matches_id (B.unwrap_expr e)
+ | _ -> false in
+ let form_ok =
+ match (form,expr) with
+ (A.ANY,_) -> true
+ | (A.CONST,e) ->
+ let rec matches = function
+ B.Constant(c) -> true
+ | B.Ident idb when idb =~ "^[A-Z_][A-Z_0-9]*$" ->
+ pr2_once ("warning: I consider " ^ idb ^ " as a constant");
+ true
+ | B.Cast(ty,e) -> matches (B.unwrap_expr e)
+ | B.Unary(e,B.UnMinus) -> matches (B.unwrap_expr e)
+ | B.SizeOfExpr(exp) -> true
+ | B.SizeOfType(ty) -> true
+ | _ -> false in
+ matches e
+ | (A.LocalID,e) ->
+ (matches_id e) &&
+ (match !opttypb with
+ (Some (_,Ast_c.LocalVar _),_) -> true
+ | _ -> false)
+ | (A.ID,e) -> matches_id e in
+
+ if form_ok
+ then
+ (let (opttypb,_testb) = !opttypb in
+ match opttypa, opttypb with
+ | None, _ -> return ((),())
+ | Some _, None ->
+ pr2_once ("Missing type information. Certainly a pb in " ^
+ "annotate_typer.ml");
+ fail
+
+ | Some tas, Some tb ->
+ tas +> List.fold_left (fun acc ta ->
+ acc >|+|> compatible_type ta tb) fail
+ ) >>=
+ (fun () () ->
+ X.check_constraints expression constraints eb
+ (fun () ->
+ let max_min _ =
+ Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_expr expb) in
+ X.envf keep inherited (ida, Ast_c.MetaExprVal expb, max_min)
+ (fun () ->
+ X.distrf_e ida expb >>= (fun ida expb ->
+ return (
+ A.MetaExpr (ida,constraints,keep,opttypa,form,inherited)+>
+ A.rewrap ea,
+ expb
+ ))
+ )))
+ else fail
+
+ (* old:
+ * | A.MetaExpr(ida,false,opttypa,_inherited), expb ->
+ * D.distribute_mck (mcodekind ida) D.distribute_mck_e expb binding
+ *
+ * but bug! because if have not tagged SP, then transform without doing
+ * any checks. Hopefully now have tagged SP technique.
+ *)
+
+
+ (* old:
+ * | A.Edots _, _ -> raise Impossible.
+ *
+ * In fact now can also have the Edots inside normal expression, not
+ * just in arg lists. in 'x[...];' less: in if(<... x ... y ...>)
+ *)
+ | A.Edots (mcode, None), expb ->
+ X.distrf_e (dots2metavar mcode) expb >>= (fun mcode expb ->
+ return (
+ A.Edots (metavar2dots mcode, None) +> A.rewrap ea ,
+ expb
+ ))
+
+
+ | A.Edots (_, Some expr), _ -> failwith "not handling when on Edots"
+
+
+ | A.Ident ida, ((B.Ident idb, typ),ii) ->
+ let ib1 = tuple_of_list1 ii in
+ ident DontKnow ida (idb, ib1) >>= (fun ida (idb, ib1) ->
+ return (
+ ((A.Ident ida)) +> wa,
+ ((B.Ident idb, typ),[ib1])
+ ))
+
+
+
+
+ | A.MetaErr _, _ -> failwith "not handling MetaErr"
+
+ (* todo?: handle some isomorphisms in int/float ? can have different
+ * format : 1l can match a 1.
+ *
+ * todo: normally string can contain some metavar too, so should
+ * recurse on the string
+ *)
+ | A.Constant (ia1), ((B.Constant (ib) , typ),ii) ->
+ (* for everything except the String case where can have multi elems *)
+ let do1 () =
+ let ib1 = tuple_of_list1 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ return (
+ ((A.Constant ia1)) +> wa,
+ ((B.Constant (ib), typ),[ib1])
+ ))
+ in
+ (match term ia1, ib with
+ | A.Int x, B.Int y ->
+ X.value_format_flag (fun use_value_equivalence ->
+ if use_value_equivalence
+ then
+ if equal_c_int x y
+ then do1()
+ else fail
+ else
+ if x =$= y
+ then do1()
+ else fail
+ )
+ | A.Char x, B.Char (y,_) when x =$= y (* todo: use kind ? *)
+ -> do1()
+ | A.Float x, B.Float (y,_) when x =$= y (* todo: use floatType ? *)
+ -> do1()
+
+ | A.String sa, B.String (sb,_kind) when sa =$= sb ->
+ (match ii with
+ | [ib1] ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ return (
+ ((A.Constant ia1)) +> wa,
+ ((B.Constant (ib), typ),[ib1])
+ ))
+ | _ -> fail (* multi string, not handled *)
+ )
+ | _, _ -> fail
+ )
+
+
+ | A.FunCall (ea, ia1, eas, ia2), ((B.FunCall (eb, ebs), typ),ii) ->
+ (* todo: do special case to allow IdMetaFunc, cos doing the
+ * recursive call will be too late, match_ident will not have the
+ * info whether it was a function. todo: but how detect when do
+ * x.field = f; how know that f is a Func ? By having computed
+ * some information before the matching!
+ *
+ * Allow match with FunCall containing types. Now ast_cocci allow
+ * type in parameter, and morover ast_cocci allow f(...) and those
+ * ... could match type.
+ *)
+ let (ib1, ib2) = tuple_of_list2 ii in
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
+ let eas = redots eas easundots in
+ return (
+ ((A.FunCall (ea, ia1, eas, ia2)) +> wa,
+ ((B.FunCall (eb, ebs),typ), [ib1;ib2])
+ ))))))
+
+
+
+
+ | A.Assignment (ea1, opa, ea2, simple),
+ ((B.Assignment (eb1, opb, eb2), typ),ii) ->
+ let (opbi) = tuple_of_list1 ii in
+ if equal_assignOp (term opa) opb
+ then
+ expression ea1 eb1 >>= (fun ea1 eb1 ->
+ expression ea2 eb2 >>= (fun ea2 eb2 ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Assignment (ea1, opa, ea2, simple))) +> wa,
+ ((B.Assignment (eb1, opb, eb2), typ), [opbi])
+ ))))
+ else fail
+
+ | A.CondExpr(ea1,ia1,ea2opt,ia2,ea3),((B.CondExpr(eb1,eb2opt,eb3),typ),ii) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ expression ea1 eb1 >>= (fun ea1 eb1 ->
+ option expression ea2opt eb2opt >>= (fun ea2opt eb2opt ->
+ expression ea3 eb3 >>= (fun ea3 eb3 ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ ((A.CondExpr(ea1,ia1,ea2opt,ia2,ea3))) +> wa,
+ ((B.CondExpr (eb1, eb2opt, eb3),typ), [ib1;ib2])
+ ))))))
+
+ (* todo?: handle some isomorphisms here ? *)
+ | A.Postfix (ea, opa), ((B.Postfix (eb, opb), typ),ii) ->
+ let opbi = tuple_of_list1 ii in
+ if equal_fixOp (term opa) opb
+ then
+ expression ea eb >>= (fun ea eb ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Postfix (ea, opa))) +> wa,
+ ((B.Postfix (eb, opb), typ),[opbi])
+ )))
+ else fail
+
+
+ | A.Infix (ea, opa), ((B.Infix (eb, opb), typ),ii) ->
+ let opbi = tuple_of_list1 ii in
+ if equal_fixOp (term opa) opb
+ then
+ expression ea eb >>= (fun ea eb ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Infix (ea, opa))) +> wa,
+ ((B.Infix (eb, opb), typ),[opbi])
+ )))
+ else fail
+
+ | A.Unary (ea, opa), ((B.Unary (eb, opb), typ),ii) ->
+ let opbi = tuple_of_list1 ii in
+ if equal_unaryOp (term opa) opb
+ then
+ expression ea eb >>= (fun ea eb ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Unary (ea, opa))) +> wa,
+ ((B.Unary (eb, opb), typ),[opbi])
+ )))
+ else fail
+
+ | A.Binary (ea1, opa, ea2), ((B.Binary (eb1, opb, eb2), typ),ii) ->
+ let opbi = tuple_of_list1 ii in
+ if equal_binaryOp (term opa) opb
+ then
+ expression ea1 eb1 >>= (fun ea1 eb1 ->
+ expression ea2 eb2 >>= (fun ea2 eb2 ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Binary (ea1, opa, ea2))) +> wa,
+ ((B.Binary (eb1, opb, eb2), typ),[opbi]
+ )))))
+ else fail
+
+ | A.Nested (ea1, opa, ea2), eb ->
+ let rec loop eb =
+ (if A.get_test_exp ea1 && not (Ast_c.is_test eb) then fail
+ else expression ea1 eb) >|+|>
+ (match eb with
+ ((B.Binary (eb1, opb, eb2), typ),ii)
+ when equal_binaryOp (term opa) opb ->
+ let opbi = tuple_of_list1 ii in
+ let left_to_right =
+ (expression ea1 eb1 >>= (fun ea1 eb1 ->
+ expression ea2 eb2 >>= (fun ea2 eb2 ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Nested (ea1, opa, ea2))) +> wa,
+ ((B.Binary (eb1, opb, eb2), typ),[opbi]
+ )))))) in
+ let right_to_left =
+ (expression ea2 eb1 >>= (fun ea2 eb1 ->
+ expression ea1 eb2 >>= (fun ea1 eb2 ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Nested (ea1, opa, ea2))) +> wa,
+ ((B.Binary (eb1, opb, eb2), typ),[opbi]
+ )))))) in
+ let in_left =
+ (loop eb1 >>= (fun ea1 eb1 ->
+ expression ea2 eb2 >>= (fun ea2 eb2 ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Nested (ea1, opa, ea2))) +> wa,
+ ((B.Binary (eb1, opb, eb2), typ),[opbi]
+ )))))) in
+ let in_right =
+ (expression ea2 eb1 >>= (fun ea2 eb1 ->
+ loop eb2 >>= (fun ea1 eb2 ->
+ tokenf opa opbi >>= (fun opa opbi ->
+ return (
+ ((A.Nested (ea1, opa, ea2))) +> wa,
+ ((B.Binary (eb1, opb, eb2), typ),[opbi]
+ )))))) in
+ left_to_right >|+|> right_to_left >|+|> in_left >|+|> in_right
+ | _ -> fail) in
+ loop eb
+
+ (* todo?: handle some isomorphisms here ? (with pointers = Unary Deref) *)
+ | A.ArrayAccess (ea1, ia1, ea2, ia2),((B.ArrayAccess (eb1, eb2), typ),ii) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ expression ea1 eb1 >>= (fun ea1 eb1 ->
+ expression ea2 eb2 >>= (fun ea2 eb2 ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ ((A.ArrayAccess (ea1, ia1, ea2, ia2))) +> wa,
+ ((B.ArrayAccess (eb1, eb2),typ), [ib1;ib2])
+ )))))
+
+ (* todo?: handle some isomorphisms here ? *)
+ | A.RecordAccess (ea, ia1, ida), ((B.RecordAccess (eb, idb), typ),ii) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ ident DontKnow ida (idb, ib2) >>= (fun ida (idb, ib2) ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ expression ea eb >>= (fun ea eb ->
+ return (
+ ((A.RecordAccess (ea, ia1, ida))) +> wa,
+ ((B.RecordAccess (eb, idb), typ), [ib1;ib2])
+ ))))
+
+
+
+ | A.RecordPtAccess (ea,ia1,ida),((B.RecordPtAccess (eb, idb), typ), ii) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ ident DontKnow ida (idb, ib2) >>= (fun ida (idb, ib2) ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ expression ea eb >>= (fun ea eb ->
+ return (
+ ((A.RecordPtAccess (ea, ia1, ida))) +> wa,
+ ((B.RecordPtAccess (eb, idb), typ), [ib1;ib2])
+ ))))
+
+
+ (* todo?: handle some isomorphisms here ?
+ * todo?: do some iso-by-absence on cast ?
+ * by trying | ea, B.Case (typb, eb) -> match_e_e ea eb ?
+ *)
+
+ | A.Cast (ia1, typa, ia2, ea), ((B.Cast (typb, eb), typ),ii) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ fullType typa typb >>= (fun typa typb ->
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ ((A.Cast (ia1, typa, ia2, ea))) +> wa,
+ ((B.Cast (typb, eb),typ),[ib1;ib2])
+ )))))
+
+ | A.SizeOfExpr (ia1, ea), ((B.SizeOfExpr (eb), typ),ii) ->
+ let ib1 = tuple_of_list1 ii in
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ return (
+ ((A.SizeOfExpr (ia1, ea))) +> wa,
+ ((B.SizeOfExpr (eb), typ),[ib1])
+ )))
+
+ | A.SizeOfType (ia1, ia2, typa, ia3), ((B.SizeOfType typb, typ),ii) ->
+ let (ib1,ib2,ib3) = tuple_of_list3 ii in
+ fullType typa typb >>= (fun typa typb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ return (
+ ((A.SizeOfType (ia1, ia2, typa, ia3))) +> wa,
+ ((B.SizeOfType (typb),typ),[ib1;ib2;ib3])
+ )))))
+
+
+ (* todo? iso ? allow all the combinations ? *)
+ | A.Paren (ia1, ea, ia2), ((B.ParenExpr (eb), typ),ii) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ ((A.Paren (ia1, ea, ia2))) +> wa,
+ ((B.ParenExpr (eb), typ), [ib1;ib2])
+ ))))
+
+ | A.NestExpr(exps,None,true), eb ->
+ (match A.unwrap exps with
+ A.DOTS [exp] ->
+ X.cocciExpExp expression exp eb >>= (fun exp eb ->
+ return (
+ (A.NestExpr(A.rewrap exps (A.DOTS [exp]),None,true)) +> wa,
+ eb
+ )
+ )
+ | _ ->
+ failwith
+ "for nestexpr, only handling the case with dots and only one exp")
+
+ | A.NestExpr _, _ ->
+ failwith "only handling multi and no when code in a nest expr"
+
+ (* only in arg lists or in define body *)
+ | A.TypeExp _, _ -> fail
+
+ (* only in arg lists *)
+ | A.MetaExprList _, _
+ | A.EComma _, _
+ | A.Ecircles _, _
+ | A.Estars _, _
+ ->
+ raise Impossible
+
+ | A.DisjExpr eas, eb ->
+ eas +> List.fold_left (fun acc ea -> acc >|+|> (expression ea eb)) fail
+
+ | A.UniqueExp _,_ | A.OptExp _,_ ->
+ failwith "not handling Opt/Unique/Multi on expr"
+
+ (* Because of Exp cant put a raise Impossible; have to put a fail *)
+
+ (* have not a counter part in coccinelle, for the moment *)
+ | _, ((B.Sequence _,_),_)
+ | _, ((B.StatementExpr _,_),_)
+ | _, ((B.Constructor _,_),_)
+ -> fail
+
+ | _, _ -> fail
+
+
+
+(* ------------------------------------------------------------------------- *)
+and (ident: info_ident -> (A.ident, string * Ast_c.info) matcher) =
+ fun infoidb ida ((idb, iib) as ib) ->
+ X.all_bound (A.get_inherited ida) >&&>
+ match A.unwrap ida with
+ | A.Id sa ->
+ if (term sa) =$= idb then
+ tokenf sa iib >>= (fun sa iib ->
+ return (
+ ((A.Id sa)) +> A.rewrap ida,
+ (idb, iib)
+ ))
+ else fail
+
+
+ | A.MetaId(mida,constraints,keep,inherited) ->
+ X.check_constraints (ident infoidb) constraints ib
+ (fun () ->
+ let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
+ (* use drop_pos for ids so that the pos is not added a second time in
+ the call to tokenf *)
+ X.envf keep inherited (A.drop_pos mida, Ast_c.MetaIdVal (idb), max_min)
+ (fun () ->
+ tokenf mida iib >>= (fun mida iib ->
+ return (
+ ((A.MetaId (mida, constraints, keep, inherited)) +> A.rewrap ida,
+ (idb, iib)
+ )))
+ ))
+
+ | A.MetaFunc(mida,constraints,keep,inherited) ->
+ let is_function _ =
+ X.check_constraints (ident infoidb) constraints ib
+ (fun () ->
+ let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
+ X.envf keep inherited (A.drop_pos mida,Ast_c.MetaFuncVal idb,max_min)
+ (fun () ->
+ tokenf mida iib >>= (fun mida iib ->
+ return (
+ ((A.MetaFunc(mida,constraints,keep,inherited)))+>A.rewrap ida,
+ (idb, iib)
+ ))
+ )) in
+ (match infoidb with
+ | LocalFunction | Function -> is_function()
+ | DontKnow ->
+ failwith "MetaFunc, need more semantic info about id"
+ (* the following implementation could possibly be useful, if one
+ follows the convention that a macro is always in capital letters
+ and that a macro is not a function.
+ (if idb =~ "^[A-Z_][A-Z_0-9]*$" then fail else is_function())*)
+ )
+
+ | A.MetaLocalFunc(mida,constraints,keep,inherited) ->
+ (match infoidb with
+ | LocalFunction ->
+ X.check_constraints (ident infoidb) constraints ib
+ (fun () ->
+ let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
+ X.envf keep inherited
+ (A.drop_pos mida,Ast_c.MetaLocalFuncVal idb, max_min)
+ (fun () ->
+ tokenf mida iib >>= (fun mida iib ->
+ return (
+ ((A.MetaLocalFunc(mida,constraints,keep,inherited)))
+ +> A.rewrap ida,
+ (idb, iib)
+ ))
+ ))
+ | Function -> fail
+ | DontKnow -> failwith "MetaLocalFunc, need more semantic info about id"
+ )
+
+ | A.OptIdent _ | A.UniqueIdent _ ->
+ failwith "not handling Opt/Unique for ident"
+
+
+
+(* ------------------------------------------------------------------------- *)
+and (arguments: sequence ->
+ (A.expression list, Ast_c.argument Ast_c.wrap2 list) matcher) =
+ fun seqstyle eas ebs ->
+ match seqstyle with
+ | Unordered -> failwith "not handling ooo"
+ | Ordered ->
+ arguments_bis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
+ return (eas, (Ast_c.unsplit_comma ebs_splitted))
+ )
+(* because '...' can match nothing, need to take care when have
+ * ', ...' or '...,' as in f(..., X, Y, ...). It must match
+ * f(1,2) for instance.
+ * So I have added special cases such as (if startxs = []) and code
+ * in the Ecomma matching rule.
+ *
+ * old: Must do some try, for instance when f(...,X,Y,...) have to
+ * test the transfo for all the combinaitions and if multiple transfo
+ * possible ? pb ? => the type is to return a expression option ? use
+ * some combinators to help ?
+ * update: with the tag-SP approach, no more a problem.
+ *)
+
+and arguments_bis = fun eas ebs ->
+ match eas, ebs with
+ | [], [] -> return ([], [])
+ | [], eb::ebs -> fail
+ | ea::eas, ebs ->
+ X.all_bound (A.get_inherited ea) >&&>
+ (match A.unwrap ea, ebs with
+ | A.Edots (mcode, optexpr), ys ->
+ (* todo: if optexpr, then a WHEN and so may have to filter yys *)
+ if optexpr <> None then failwith "not handling when in argument";
+
+ (* '...' can take more or less the beginnings of the arguments *)
+ let startendxs = Common.zip (Common.inits ys) (Common.tails ys) in
+ startendxs +> List.fold_left (fun acc (startxs, endxs) ->
+ acc >||> (
+
+ (* allow '...', and maybe its associated ',' to match nothing.
+ * for the associated ',' see below how we handle the EComma
+ * to match nothing.
+ *)
+ (if startxs = []
+ then
+ if mcode_contain_plus (mcodekind mcode)
+ then fail
+ (* failwith "I have no token that I could accroche myself on" *)
+ else return (dots2metavar mcode, [])
+ else
+ (* subtil: we dont want the '...' to match until the
+ * comma. cf -test pb_params_iso. We would get at
+ * "already tagged" error.
+ * this is because both f (... x, ...) and f (..., x, ...)
+ * would match a f(x,3) with our "optional-comma" strategy.
+ *)
+ (match Common.last startxs with
+ | Right _ -> fail
+ | Left _ ->
+ X.distrf_args (dots2metavar mcode) startxs
+ )
+ )
+ >>= (fun mcode startxs ->
+ let mcode = metavar2dots mcode in
+ arguments_bis eas endxs >>= (fun eas endxs ->
+ return (
+ (A.Edots (mcode, optexpr) +> A.rewrap ea) ::eas,
+ startxs ++ endxs
+ )))
+ )
+ ) fail
+
+ | A.EComma ia1, Right ii::ebs ->
+ let ib1 = tuple_of_list1 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ arguments_bis eas ebs >>= (fun eas ebs ->
+ return (
+ (A.EComma ia1 +> A.rewrap ea)::eas,
+ (Right [ib1])::ebs
+ )
+ ))
+ | A.EComma ia1, ebs ->
+ (* allow ',' to maching nothing. optional comma trick *)
+ if mcode_contain_plus (mcodekind ia1)
+ then fail
+ else arguments_bis eas ebs
+
+ | A.MetaExprList(ida,leninfo,keep,inherited),ys ->
+ let startendxs = Common.zip (Common.inits ys) (Common.tails ys) in
+ startendxs +> List.fold_left (fun acc (startxs, endxs) ->
+ acc >||> (
+ let ok =
+ if startxs = []
+ then
+ if mcode_contain_plus (mcodekind ida)
+ then false
+ (* failwith "no token that I could accroche myself on" *)
+ else true
+ else
+ (match Common.last startxs with
+ | Right _ -> false
+ | Left _ -> true
+ )
+ in
+ if not ok
+ then fail
+ else
+ let startxs' = Ast_c.unsplit_comma startxs in
+ let len = List.length startxs' in
+
+ (match leninfo with
+ | Some (lenname,lenkeep,leninherited) ->
+ let max_min _ = failwith "no pos" in
+ X.envf lenkeep leninherited
+ (lenname, Ast_c.MetaListlenVal (len), max_min)
+ | None -> function f -> f()
+ )
+ (fun () ->
+ let max_min _ =
+ Lib_parsing_c.lin_col_by_pos
+ (Lib_parsing_c.ii_of_args startxs) in
+ X.envf keep inherited
+ (ida, Ast_c.MetaExprListVal startxs', max_min)
+ (fun () ->
+ if startxs = []
+ then return (ida, [])
+ else X.distrf_args ida (Ast_c.split_comma startxs')
+ )
+ >>= (fun ida startxs ->
+ arguments_bis eas endxs >>= (fun eas endxs ->
+ return (
+ (A.MetaExprList(ida,leninfo,keep,inherited))
+ +> A.rewrap ea::eas,
+ startxs ++ endxs
+ ))
+ )
+ )
+ )) fail
+
+
+ | _unwrapx, (Left eb)::ebs ->
+ argument ea eb >>= (fun ea eb ->
+ arguments_bis eas ebs >>= (fun eas ebs ->
+ return (ea::eas, Left eb::ebs)
+ ))
+ | _unwrapx, (Right y)::ys -> raise Impossible
+ | _unwrapx, [] -> fail
+ )
+
+
+and argument arga argb =
+ X.all_bound (A.get_inherited arga) >&&>
+ match A.unwrap arga, argb with
+ | A.TypeExp tya, Right (B.ArgType (((b, sopt, tyb), ii_b_s))) ->
+
+ if b || sopt <> None
+ then
+ (* failwith "the argument have a storage and ast_cocci does not have"*)
+ fail
+ else
+ fullType tya tyb >>= (fun tya tyb ->
+ return (
+ (A.TypeExp tya) +> A.rewrap arga,
+ (Right (B.ArgType (((b, sopt, tyb), ii_b_s))))
+ ))
+
+ | A.TypeExp tya, _ -> fail
+ | _, Right (B.ArgType (tyb, sto_iisto)) -> fail
+ | _, Left argb ->
+ expression arga argb >>= (fun arga argb ->
+ return (arga, Left argb)
+ )
+ | _, Right (B.ArgAction y) -> fail
+
+
+(* ------------------------------------------------------------------------- *)
+(* todo? facto code with argument ? *)
+and (parameters: sequence ->
+ (A.parameterTypeDef list, Ast_c.parameterType Ast_c.wrap2 list)
+ matcher) =
+ fun seqstyle eas ebs ->
+ match seqstyle with
+ | Unordered -> failwith "not handling ooo"
+ | Ordered ->
+ parameters_bis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
+ return (eas, (Ast_c.unsplit_comma ebs_splitted))
+ )
+
+
+and parameters_bis eas ebs =
+ match eas, ebs with
+ | [], [] -> return ([], [])
+ | [], eb::ebs -> fail
+ | ea::eas, ebs ->
+ (* the management of positions is inlined into each case, because
+ sometimes there is a Param and sometimes a ParamList *)
+ X.all_bound (A.get_inherited ea) >&&>
+ (match A.unwrap ea, ebs with
+ | A.Pdots (mcode), ys ->
+
+ (* '...' can take more or less the beginnings of the arguments *)
+ let startendxs = Common.zip (Common.inits ys) (Common.tails ys) in
+ startendxs +> List.fold_left (fun acc (startxs, endxs) ->
+ acc >||> (
+
+ (if startxs = []
+ then
+ if mcode_contain_plus (mcodekind mcode)
+ then fail
+ (* failwith "I have no token that I could accroche myself on"*)
+ else return (dots2metavar mcode, [])
+ else
+ (match Common.last startxs with
+ | Right _ -> fail
+ | Left _ ->
+ X.distrf_params (dots2metavar mcode) startxs
+ )
+ ) >>= (fun mcode startxs ->
+ let mcode = metavar2dots mcode in
+ parameters_bis eas endxs >>= (fun eas endxs ->
+ return (
+ (A.Pdots (mcode) +> A.rewrap ea) ::eas,
+ startxs ++ endxs
+ )))
+ )
+ ) fail
+
+ | A.PComma ia1, Right ii::ebs ->
+ let ib1 = tuple_of_list1 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ parameters_bis eas ebs >>= (fun eas ebs ->
+ return (
+ (A.PComma ia1 +> A.rewrap ea)::eas,
+ (Right [ib1])::ebs
+ )
+ ))
+
+ | A.PComma ia1, ebs ->
+ (* try optional comma trick *)
+ if mcode_contain_plus (mcodekind ia1)
+ then fail
+ else parameters_bis eas ebs
+
+
+ | A.MetaParamList(ida,leninfo,keep,inherited),ys->
+ let startendxs = Common.zip (Common.inits ys) (Common.tails ys) in
+ startendxs +> List.fold_left (fun acc (startxs, endxs) ->
+ acc >||> (
+ let ok =
+ if startxs = []
+ then
+ if mcode_contain_plus (mcodekind ida)
+ then false
+ (* failwith "I have no token that I could accroche myself on" *)
+ else true
+ else
+ (match Common.last startxs with
+ | Right _ -> false
+ | Left _ -> true
+ )
+ in
+ if not ok
+ then fail
+ else
+ let startxs' = Ast_c.unsplit_comma startxs in
+ let len = List.length startxs' in
+
+ (match leninfo with
+ Some (lenname,lenkeep,leninherited) ->
+ let max_min _ = failwith "no pos" in
+ X.envf lenkeep leninherited
+ (lenname, Ast_c.MetaListlenVal (len), max_min)
+ | None -> function f -> f()
+ )
+ (fun () ->
+ let max_min _ =
+ Lib_parsing_c.lin_col_by_pos
+ (Lib_parsing_c.ii_of_params startxs) in
+ X.envf keep inherited
+ (ida, Ast_c.MetaParamListVal startxs', max_min)
+ (fun () ->
+ if startxs = []
+ then return (ida, [])
+ else X.distrf_params ida (Ast_c.split_comma startxs')
+ ) >>= (fun ida startxs ->
+ parameters_bis eas endxs >>= (fun eas endxs ->
+ return (
+ (A.MetaParamList(ida,leninfo,keep,inherited))
+ +> A.rewrap ea::eas,
+ startxs ++ endxs
+ ))
+ )
+ ))
+ ) fail
+
+
+ | A.VoidParam ta, ys ->
+ (match eas, ebs with
+ | [], [Left eb] ->
+ let ((hasreg, idbopt, tb), ii_b_s) = eb in
+ if idbopt = None && null ii_b_s
+ then
+ match tb with
+ | (qub, (B.BaseType B.Void,_)) ->
+ fullType ta tb >>= (fun ta tb ->
+ return (
+ [(A.VoidParam ta) +> A.rewrap ea],
+ [Left ((hasreg, idbopt, tb), ii_b_s)]
+ ))
+ | _ -> fail
+ else fail
+ | _ -> fail
+ )
+
+ | (A.OptParam _ | A.UniqueParam _), _ ->
+ failwith "handling Opt/Unique for Param"
+
+ | A.Pcircles (_), ys -> raise Impossible (* in Ordered mode *)
+
+
+ | A.MetaParam (ida,keep,inherited), (Left eb)::ebs ->
+ (* todo: use quaopt, hasreg ? *)
+ let max_min _ =
+ Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_param eb) in
+ X.envf keep inherited (ida,Ast_c.MetaParamVal eb,max_min) (fun () ->
+ X.distrf_param ida eb
+ ) >>= (fun ida eb ->
+ parameters_bis eas ebs >>= (fun eas ebs ->
+ return (
+ (A.MetaParam(ida,keep,inherited))+> A.rewrap ea::eas,
+ (Left eb)::ebs
+ )))
+
+
+ | A.Param (typa, idaopt), (Left eb)::ebs ->
+ (*this should succeed if the C code has a name, and fail otherwise*)
+ parameter (idaopt, typa) eb >>= (fun (idaopt, typa) eb ->
+ parameters_bis eas ebs >>= (fun eas ebs ->
+ return (
+ (A.Param (typa, idaopt))+> A.rewrap ea :: eas,
+ (Left eb)::ebs
+ )))
+
+ | _unwrapx, (Right y)::ys -> raise Impossible
+ | _unwrapx, [] -> fail
+ )
+
+
+
+
+
+and parameter = fun (idaopt, typa) ((hasreg, idbopt, typb), ii_b_s) ->
+ fullType typa typb >>= (fun typa typb ->
+ match idaopt, Ast_c.split_register_param (hasreg, idbopt, ii_b_s) with
+ | Some ida, Left (idb, iihasreg, iidb) ->
+ (* todo: if minus on ida, should also minus the iihasreg ? *)
+ ident DontKnow ida (idb,iidb) >>= (fun ida (idb,iidb) ->
+ return (
+ (Some ida, typa),
+ ((hasreg, Some idb, typb), iihasreg++[iidb])
+ ))
+
+ | None, Right iihasreg ->
+ return (
+ (None, typa),
+ ((hasreg, None, typb), iihasreg)
+ )
+
+
+ (* why handle this case ? because of transform_proto ? we may not
+ * have an ident in the proto.
+ * If have some plus on ida ? do nothing about ida ?
+ *)
+ (* not anymore !!! now that julia is handling the proto.
+ | _, Right iihasreg ->
+ return (
+ (idaopt, typa),
+ ((hasreg, None, typb), iihasreg)
+ )
+ *)
+
+ | Some _, Right _ -> fail
+ | None, Left _ -> fail
+ )
+
+
+
+
+(* ------------------------------------------------------------------------- *)
+and (declaration: (A.mcodekind * bool * A.declaration,B.declaration) matcher) =
+ fun (mckstart, allminus, decla) declb ->
+ X.all_bound (A.get_inherited decla) >&&>
+ match A.unwrap decla, declb with
+
+ (* Un MetaDecl est introduit dans l'asttoctl pour sauter au dessus
+ * de toutes les declarations qui sont au debut d'un fonction et
+ * commencer le reste du match au premier statement. Alors, ca matche
+ * n'importe quelle declaration. On n'a pas besoin d'ajouter
+ * quoi que ce soit dans l'environnement. C'est une sorte de DDots.
+ *
+ * When the SP want to remove the whole function, the minus is not
+ * on the MetaDecl but on the MetaRuleElem. So there should
+ * be no transform of MetaDecl, just matching are allowed.
+ *)
+
+ | A.MetaDecl(ida,_keep,_inherited), _ -> (* keep ? inherited ? *)
+ (* todo: should not happen in transform mode *)
+ return ((mckstart, allminus, decla), declb)
+
+
+
+ | _, (B.DeclList ([var], iiptvirgb::iifakestart::iisto)) ->
+ onedecl allminus decla (var,iiptvirgb,iisto) >>=
+ (fun decla (var,iiptvirgb,iisto)->
+ X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
+ return (
+ (mckstart, allminus, decla),
+ (B.DeclList ([var], iiptvirgb::iifakestart::iisto))
+ )))
+
+ | _, (B.DeclList (xs, iiptvirgb::iifakestart::iisto)) ->
+ if X.mode = PatternMode
+ then
+ xs +> List.fold_left (fun acc var ->
+ acc >||> (
+ X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
+ onedecl allminus decla (var, iiptvirgb, iisto) >>=
+ (fun decla (var, iiptvirgb, iisto) ->
+ return (
+ (mckstart, allminus, decla),
+ (B.DeclList ([var], iiptvirgb::iifakestart::iisto))
+ )))))
+ fail
+ else
+ failwith "More that one variable in decl. Have to split to transform."
+
+ | A.MacroDecl (sa,lpa,eas,rpa,enda), B.MacroDecl ((sb,ebs),ii) ->
+ let (iisb, lpb, rpb, iiendb, iifakestart, iistob) =
+ (match ii with
+ | iisb::lpb::rpb::iiendb::iifakestart::iisto ->
+ (iisb,lpb,rpb,iiendb, iifakestart,iisto)
+ | _ -> raise Impossible
+ ) in
+ (if allminus
+ then minusize_list iistob
+ else return ((), iistob)
+ ) >>= (fun () iistob ->
+
+ X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
+ ident DontKnow sa (sb, iisb) >>= (fun sa (sb, iisb) ->
+ tokenf lpa lpb >>= (fun lpa lpb ->
+ tokenf rpa rpb >>= (fun rpa rpb ->
+ tokenf enda iiendb >>= (fun enda iiendb ->
+ arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
+ let eas = redots eas easundots in
+
+ return (
+ (mckstart, allminus,
+ (A.MacroDecl (sa,lpa,eas,rpa,enda)) +> A.rewrap decla),
+ (B.MacroDecl ((sb,ebs),
+ [iisb;lpb;rpb;iiendb;iifakestart] ++ iistob))
+ ))))))))
+
+ | _ -> fail
+
+
+
+and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
+ X.all_bound (A.get_inherited decla) >&&>
+ match A.unwrap decla, declb with
+
+ (* kind of typedef iso, we must unfold, it's for the case
+ * T { }; that we want to match against typedef struct { } xx_t;
+ *)
+ | A.TyDecl (tya0, ptvirga),
+ ((Some ((idb, None),[iidb]), typb0, (B.StoTypedef, inl), local), iivirg) ->
+
+ (match A.unwrap tya0, typb0 with
+ | A.Type(cv1,tya1), ((qu,il),typb1) ->
+
+ (match A.unwrap tya1, typb1 with
+ | A.StructUnionDef(tya2, lba, declsa, rba),
+ (B.StructUnion (sub, sbopt, declsb), ii) ->
+
+ let (iisub, iisbopt, lbb, rbb) =
+ match sbopt with
+ | None ->
+ let (iisub, lbb, rbb) = tuple_of_list3 ii in
+ (iisub, [], lbb, rbb)
+ | Some s ->
+ pr2 (sprintf
+ "warning: both a typedef (%s) and struct name introduction (%s)"
+ idb s
+ );
+ pr2 "warning: I will consider only the typedef";
+ let (iisub, iisb, lbb, rbb) = tuple_of_list4 ii in
+ (iisub, [iisb], lbb, rbb)
+ in
+ let structnameb =
+ structdef_to_struct_name
+ (Ast_c.nQ, (B.StructUnion (sub, sbopt, declsb), ii))
+ in
+ let fake_typeb =
+ Ast_c.nQ,((B.TypeName (idb, Some
+ (Lib_parsing_c.al_type structnameb))), [iidb])
+ in
+
+ tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
+ tokenf lba lbb >>= (fun lba lbb ->
+ tokenf rba rbb >>= (fun rba rbb ->
+ struct_fields (A.undots declsa) declsb >>=(fun undeclsa declsb ->
+ let declsa = redots declsa undeclsa in
+
+ (match A.unwrap tya2 with
+ | A.Type(cv3, tya3) ->
+ (match A.unwrap tya3 with
+ | A.MetaType(ida,keep, inherited) ->
+
+ fullType tya2 fake_typeb >>= (fun tya2 fake_typeb ->
+ let tya1 =
+ A.StructUnionDef(tya2,lba,declsa,rba)+> A.rewrap tya1 in
+ let tya0 = A.Type(cv1, tya1) +> A.rewrap tya0 in
+
+
+ let typb1 = B.StructUnion (sub,sbopt, declsb),
+ [iisub] @ iisbopt @ [lbb;rbb] in
+ let typb0 = ((qu, il), typb1) in
+
+ match fake_typeb with
+ | _nQ, ((B.TypeName (idb,_typ)), [iidb]) ->
+
+ return (
+ (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
+ (((Some ((idb, None),[iidb]), typb0, (B.StoTypedef, inl),
+ local),
+ iivirg),iiptvirgb,iistob)
+ )
+ | _ -> raise Impossible
+ )
+
+ | A.StructUnionName(sua, sa) ->
+
+ fullType tya2 structnameb >>= (fun tya2 structnameb ->
+
+ let tya1 = A.StructUnionDef(tya2,lba,declsa,rba)+> A.rewrap tya1
+ in
+ let tya0 = A.Type(cv1, tya1) +> A.rewrap tya0 in
+
+ match structnameb with
+ | _nQ, (B.StructUnionName (sub, s), [iisub;iisbopt]) ->
+
+ let typb1 = B.StructUnion (sub,sbopt, declsb),
+ [iisub;iisbopt;lbb;rbb] in
+ let typb0 = ((qu, il), typb1) in
+
+ return (
+ (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
+ (((Some ((idb, None),[iidb]), typb0,
+ (B.StoTypedef, inl), local),
+ iivirg),iiptvirgb,iistob)
+ )
+ | _ -> raise Impossible
+ )
+ | _ -> raise Impossible
+ )
+ | _ -> fail
+ )))))
+ | _ -> fail
+ )
+ | _ -> fail
+ )
+
+ | A.UnInit (stoa, typa, ida, ptvirga),
+ ((Some ((idb, _),[iidb]), typb, (B.StoTypedef,_), _local), iivirg) ->
+ fail
+
+ | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
+ ((Some ((idb, _),[iidb]), typb, (B.StoTypedef,_), _local), iivirg) ->
+ fail
+
+
+
+ (* could handle iso here but handled in standard.iso *)
+ | A.UnInit (stoa, typa, ida, ptvirga),
+ ((Some ((idb, None),[iidb]), typb, stob, local), iivirg) ->
+ tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
+ fullType typa typb >>= (fun typa typb ->
+ ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
+ storage_optional_allminus allminus stoa (stob, iistob) >>=
+ (fun stoa (stob, iistob) ->
+ return (
+ (A.UnInit (stoa, typa, ida, ptvirga)) +> A.rewrap decla,
+ (((Some ((idb,None),[iidb]),typb,stob,local),iivirg),
+ iiptvirgb,iistob)
+ )))))
+
+ | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
+ ((Some((idb,Some inib),[iidb;iieqb]),typb,stob,local),iivirg)
+ ->
+ tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
+ tokenf eqa iieqb >>= (fun eqa iieqb ->
+ fullType typa typb >>= (fun typa typb ->
+ ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
+ storage_optional_allminus allminus stoa (stob, iistob) >>=
+ (fun stoa (stob, iistob) ->
+ initialiser inia inib >>= (fun inia inib ->
+ return (
+ (A.Init (stoa, typa, ida, eqa, inia, ptvirga)) +> A.rewrap decla,
+ (((Some((idb,Some inib),[iidb;iieqb]),typb,stob,local),iivirg),
+ iiptvirgb,iistob)
+ )))))))
+
+ (* do iso-by-absence here ? allow typedecl and var ? *)
+ | A.TyDecl (typa, ptvirga), ((None, typb, stob, local), iivirg) ->
+ if stob = (B.NoSto, false)
+ then
+ tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
+ fullType typa typb >>= (fun typa typb ->
+ return (
+ (A.TyDecl (typa, ptvirga)) +> A.rewrap decla,
+ (((None, typb, stob, local), iivirg), iiptvirgb, iistob)
+ )))
+ else fail
+
+
+ | A.Typedef (stoa, typa, ida, ptvirga),
+ ((Some ((idb, None),[iidb]),typb,(B.StoTypedef,inline),local),iivirg) ->
+
+ tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
+ fullType typa typb >>= (fun typa typb ->
+ (match iistob with
+ | [iitypedef] ->
+ tokenf stoa iitypedef >>= (fun stoa iitypedef ->
+ return (stoa, [iitypedef])
+ )
+ | _ -> failwith "wierd, have both typedef and inline or nothing";
+ ) >>= (fun stoa iistob ->
+ (match A.unwrap ida with
+ | A.MetaType(_,_,_) ->
+
+ let fake_typeb =
+ Ast_c.nQ, ((B.TypeName (idb, Ast_c.noTypedefDef())), [iidb])
+ in
+ fullTypebis ida fake_typeb >>= (fun ida fake_typeb ->
+ match fake_typeb with
+ | _nQ, ((B.TypeName (idb,_typ)), [iidb]) ->
+ return (ida, (idb, iidb))
+ | _ -> raise Impossible
+ )
+
+ | A.TypeName sa ->
+ if (term sa) =$= idb
+ then
+ tokenf sa iidb >>= (fun sa iidb ->
+ return (
+ (A.TypeName sa) +> A.rewrap ida,
+ (idb, iidb)
+ ))
+ else fail
+ | _ -> raise Impossible
+
+ ) >>= (fun ida (idb, iidb) ->
+ return (
+ (A.Typedef (stoa, typa, ida, ptvirga)) +> A.rewrap decla,
+ (((Some ((idb, None),[iidb]), typb, (B.StoTypedef,inline),local),
+ iivirg),
+ iiptvirgb, iistob)
+ )
+ ))))
+
+
+ | _, ((None, typb, sto, _local), _) ->
+ (* old: failwith "no variable in this declaration, wierd" *)
+ fail
+
+
+
+ | A.DisjDecl declas, declb ->
+ declas +> List.fold_left (fun acc decla ->
+ acc >|+|>
+ (* (declaration (mckstart, allminus, decla) declb) *)
+ (onedecl allminus decla (declb,iiptvirgb, iistob))
+ ) fail
+
+
+
+ (* only in struct type decls *)
+ | A.Ddots(dots,whencode), _ ->
+ raise Impossible
+
+ | A.OptDecl _, _ | A.UniqueDecl _, _ ->
+ failwith "not handling Opt/Unique Decl"
+
+
+ | _, _ -> fail
+
+
+
+(* ------------------------------------------------------------------------- *)
+
+and (initialiser: (A.initialiser, Ast_c.initialiser) matcher) = fun ia ib ->
+ X.all_bound (A.get_inherited ia) >&&>
+ match (A.unwrap ia,ib) with
+
+ | (A.InitExpr expa, ib) ->
+ (match A.unwrap expa, ib with
+ | A.Edots (mcode, None), ib ->
+ X.distrf_ini (dots2metavar mcode) ib >>= (fun mcode ib ->
+ return (
+ A.InitExpr
+ (A.Edots (metavar2dots mcode, None) +> A.rewrap expa)
+ +> A.rewrap ia,
+ ib
+ ))
+
+ | A.Edots (_, Some expr), _ -> failwith "not handling when on Edots"
+
+ | _, (B.InitExpr expb, ii) ->
+ assert (null ii);
+ expression expa expb >>= (fun expa expb ->
+ return (
+ (A.InitExpr expa) +> A.rewrap ia,
+ (B.InitExpr expb, ii)
+ ))
+ | _ -> fail
+ )
+
+ | (A.InitList (ia1, ias, ia2, []), (B.InitList ibs, ii)) ->
+ (match ii with
+ | ib1::ib2::iicommaopt ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ initialisers ias (ibs, iicommaopt) >>= (fun ias (ibs,iicommaopt) ->
+ return (
+ (A.InitList (ia1, ias, ia2, [])) +> A.rewrap ia,
+ (B.InitList ibs, ib1::ib2::iicommaopt)
+ ))))
+
+ | _ -> raise Impossible
+ )
+
+ | (A.InitList (i1, ias, i2, whencode),(B.InitList ibs, _ii)) ->
+ failwith "TODO: not handling whencode in initialisers"
+
+
+ | (A.InitGccDotName (ia1, ida, ia2, inia),
+ (B.InitDesignators ([B.DesignatorField idb,ii1], inib), ii2))->
+
+ let (iidot, iidb) = tuple_of_list2 ii1 in
+ let iieq = tuple_of_list1 ii2 in
+
+ tokenf ia1 iidot >>= (fun ia1 iidot ->
+ tokenf ia2 iieq >>= (fun ia2 iieq ->
+ ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
+ initialiser inia inib >>= (fun inia inib ->
+ return (
+ (A.InitGccDotName (ia1, ida, ia2, inia)) +> A.rewrap ia,
+ (B.InitDesignators
+ ([B.DesignatorField idb, [iidot;iidb]], inib), [iieq])
+ )))))
+
+
+ | (A.InitGccIndex (ia1,ea,ia2,ia3,inia),
+ (B.InitDesignators ([B.DesignatorIndex eb, ii1], inib), ii2)) ->
+
+ let (ib1, ib2) = tuple_of_list2 ii1 in
+ let ib3 = tuple_of_list1 ii2 in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ expression ea eb >>= (fun ea eb ->
+ initialiser inia inib >>= (fun inia inib ->
+ return (
+ (A.InitGccIndex (ia1,ea,ia2,ia3,inia)) +> A.rewrap ia,
+ (B.InitDesignators
+ ([B.DesignatorIndex eb, [ib1;ib2]], inib), [ib3])
+ ))))))
+
+
+ | (A.InitGccRange (ia1,e1a,ia2,e2a,ia3,ia4,inia),
+ (B.InitDesignators ([B.DesignatorRange (e1b, e2b), ii1], inib), ii2)) ->
+
+ let (ib1, ib2, ib3) = tuple_of_list3 ii1 in
+ let (ib4) = tuple_of_list1 ii2 in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ tokenf ia4 ib4 >>= (fun ia4 ib4 ->
+ expression e1a e1b >>= (fun e1a e1b ->
+ expression e2a e2b >>= (fun e2a e2b ->
+ initialiser inia inib >>= (fun inia inib ->
+ return (
+ (A.InitGccRange (ia1,e1a,ia2,e2a,ia3,ia4,inia)) +> A.rewrap ia,
+ (B.InitDesignators
+ ([B.DesignatorRange (e1b, e2b),[ib1;ib2;ib3]], inib), [ib4])
+ ))))))))
+
+
+
+
+ | (A.InitGccName (ida, ia1, inia), (B.InitFieldOld (idb, inib), ii)) ->
+ (match ii with
+ | [iidb;iicolon] ->
+ ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
+ initialiser inia inib >>= (fun inia inib ->
+ tokenf ia1 iicolon >>= (fun ia1 iicolon ->
+ return (
+ (A.InitGccName (ida, ia1, inia)) +> A.rewrap ia,
+ (B.InitFieldOld (idb, inib), [iidb;iicolon])
+ ))))
+ | _ -> fail
+ )
+
+
+
+ | A.IComma(comma), _ ->
+ raise Impossible
+
+ | A.UniqueIni _,_ | A.OptIni _,_ ->
+ failwith "not handling Opt/Unique on initialisers"
+
+ | _, _ -> fail
+
+
+
+
+
+and initialisers = fun ias (ibs, iicomma) ->
+ let ias_unsplit = unsplit_icomma ias in
+ let ibs_split = resplit_initialiser ibs iicomma in
+
+ let f =
+ if need_unordered_initialisers ibs
+ then initialisers_unordered2
+ else initialisers_ordered2
+ in
+ f ias_unsplit ibs_split >>=
+ (fun ias_unsplit ibs_split ->
+ return (
+ split_icomma ias_unsplit,
+ unsplit_initialiser ibs_split
+ )
+ )
+
+(* todo: one day julia will reput a IDots *)
+and initialisers_ordered2 = fun ias ibs ->
+ match ias, ibs with
+ | [], [] -> return ([], [])
+ | (x, xcomma)::xs, (y, commay)::ys ->
+ (match A.unwrap xcomma with
+ | A.IComma commax ->
+ tokenf commax commay >>= (fun commax commay ->
+ initialiser x y >>= (fun x y ->
+ initialisers_ordered2 xs ys >>= (fun xs ys ->
+ return (
+ (x, (A.IComma commax) +> A.rewrap xcomma)::xs,
+ (y, commay)::ys
+ )
+ )))
+ | _ -> raise Impossible (* unsplit_iicomma wrong *)
+ )
+ | _ -> fail
+
+
+
+and initialisers_unordered2 = fun ias ibs ->
+
+ match ias, ibs with
+ | [], ys -> return ([], ys)
+ | (x,xcomma)::xs, ys ->
+
+ let permut = Common.uncons_permut_lazy ys in
+ permut +> List.fold_left (fun acc ((e, pos), rest) ->
+ acc >||>
+ (
+ (match A.unwrap xcomma, e with
+ | A.IComma commax, (y, commay) ->
+ tokenf commax commay >>= (fun commax commay ->
+ initialiser x y >>= (fun x y ->
+ return (
+ (x, (A.IComma commax) +> A.rewrap xcomma),
+ (y, commay))
+ )
+ )
+ | _ -> raise Impossible (* unsplit_iicomma wrong *)
+ )
+ >>= (fun x e ->
+ let rest = Lazy.force rest in
+ initialisers_unordered2 xs rest >>= (fun xs rest ->
+ return (
+ x::xs,
+ Common.insert_elem_pos (e, pos) rest
+ ))))
+ ) fail
+
+
+(* ------------------------------------------------------------------------- *)
+and (struct_fields: (A.declaration list, B.field B.wrap list) matcher) =
+ fun eas ebs ->
+ match eas, ebs with
+ | [], [] -> return ([], [])
+ | [], eb::ebs -> fail
+ | ea::eas, ebs ->
+ X.all_bound (A.get_inherited ea) >&&>
+ (match A.unwrap ea, ebs with
+ | A.Ddots (mcode, optwhen), ys ->
+ if optwhen <> None then failwith "not handling when in argument";
+
+ (* '...' can take more or less the beginnings of the arguments *)
+ let startendxs = Common.zip (Common.inits ys) (Common.tails ys) in
+ startendxs +> List.fold_left (fun acc (startxs, endxs) ->
+ acc >||> (
+
+ (if startxs = []
+ then
+ if mcode_contain_plus (mcodekind mcode)
+ then fail
+ (* failwith "I have no token that I could accroche myself on" *)
+ else return (dots2metavar mcode, [])
+ else
+
+ X.distrf_struct_fields (dots2metavar mcode) startxs
+ ) >>= (fun mcode startxs ->
+ let mcode = metavar2dots mcode in
+ struct_fields eas endxs >>= (fun eas endxs ->
+ return (
+ (A.Ddots (mcode, optwhen) +> A.rewrap ea) ::eas,
+ startxs ++ endxs
+ )))
+ )
+ ) fail
+ | _unwrapx, eb::ebs ->
+ struct_field ea eb >>= (fun ea eb ->
+ struct_fields eas ebs >>= (fun eas ebs ->
+ return (ea::eas, eb::ebs)
+ ))
+
+ | _unwrapx, [] -> fail
+ )
+
+and (struct_field: (A.declaration, B.field B.wrap) matcher) = fun fa fb ->
+ let (xfield, ii) = fb in
+ let iiptvirgb = tuple_of_list1 ii in
+
+ match xfield with
+ | B.FieldDeclList onefield_multivars ->
+
+ (match onefield_multivars with
+ | [] -> raise Impossible
+ | [onevar,iivirg] ->
+ assert (null iivirg);
+ (match onevar with
+ | B.BitField (sopt, typb, expr), ii ->
+ pr2_once "warning: bitfield not handled by ast_cocci";
+ fail
+ | B.Simple (None, typb), ii ->
+ pr2_once "warning: unamed struct field not handled by ast_cocci";
+ fail
+ | B.Simple (Some idb, typb), ii ->
+ let (iidb) = tuple_of_list1 ii in
+
+ (* build a declaration from a struct field *)
+ let allminus = false in
+ let iisto = [] in
+ let stob = B.NoSto, false in
+ let fake_var =
+ ((Some ((idb, None),[iidb]), typb, stob, Ast_c.NotLocalDecl),
+ iivirg)
+ in
+ onedecl allminus fa (fake_var,iiptvirgb,iisto) >>=
+ (fun fa (var,iiptvirgb,iisto) ->
+
+ match fake_var with
+ | ((Some ((idb, None),[iidb]), typb, stob, local), iivirg) ->
+ let onevar = B.Simple (Some idb, typb), [iidb] in
+
+ return (
+ (fa),
+ (B.FieldDeclList [onevar, iivirg], [iiptvirgb])
+ )
+ | _ -> raise Impossible
+ )
+ )
+
+ | x::y::xs ->
+ pr2_once "PB: More that one variable in decl. Have to split";
+ fail
+ )
+ | B.EmptyField -> fail
+
+
+
+(* ------------------------------------------------------------------------- *)
+and (fullType: (A.fullType, Ast_c.fullType) matcher) =
+ fun typa typb ->
+ X.optional_qualifier_flag (fun optional_qualifier ->
+ X.all_bound (A.get_inherited typa) >&&>
+ match A.unwrap typa, typb with
+ | A.Type(cv,ty1), ((qu,il),ty2) ->
+
+ if qu.B.const && qu.B.volatile
+ then
+ pr2_once
+ ("warning: the type is both const & volatile but cocci " ^
+ "does not handle that");
+
+ (* Drop out the const/volatile part that has been matched.
+ * This is because a SP can contain const T v; in which case
+ * later in match_t_t when we encounter a T, we must not add in
+ * the environment the whole type.
+ *)
+
+
+ (match cv with
+ (* "iso-by-absence" *)
+ | None ->
+ let do_stuff () =
+ fullTypebis ty1 ((qu,il), ty2) >>= (fun ty1 fullty2 ->
+ return (
+ (A.Type(None, ty1)) +> A.rewrap typa,
+ fullty2
+ ))
+ in
+ (match optional_qualifier, qu.B.const || qu.B.volatile with
+ | false, false -> do_stuff ()
+ | false, true -> fail
+ | true, false -> do_stuff ()
+ | true, true ->
+ if !Flag.show_misc
+ then pr2_once "USING optional_qualifier builtin isomorphism";
+ do_stuff()
+ )
+
+
+ | Some x ->
+ (* todo: can be __const__ ? can be const & volatile so
+ * should filter instead ?
+ *)
+ (match term x, il with
+ | A.Const, [i1] when qu.B.const ->
+
+ tokenf x i1 >>= (fun x i1 ->
+ fullTypebis ty1 (Ast_c.nQ,ty2) >>= (fun ty1 (_, ty2) ->
+ return (
+ (A.Type(Some x, ty1)) +> A.rewrap typa,
+ ((qu, [i1]), ty2)
+ )))
+
+ | A.Volatile, [i1] when qu.B.volatile ->
+ tokenf x i1 >>= (fun x i1 ->
+ fullTypebis ty1 (Ast_c.nQ,ty2) >>= (fun ty1 (_, ty2) ->
+ return (
+ (A.Type(Some x, ty1)) +> A.rewrap typa,
+ ((qu, [i1]), ty2)
+ )))
+
+ | _ -> fail
+ )
+ )
+
+ | A.DisjType typas, typb ->
+ typas +>
+ List.fold_left (fun acc typa -> acc >|+|> (fullType typa typb)) fail
+
+ | A.OptType(_), _ | A.UniqueType(_), _
+ -> failwith "not handling Opt/Unique on type"
+ )
+
+
+(*
+ * Why not (A.typeC, Ast_c.typeC) matcher ?
+ * because when there is MetaType, we want that T record the whole type,
+ * including the qualifier, and so this type (and the new_il function in
+ * preceding function).
+*)
+
+and (fullTypebis: (A.typeC, Ast_c.fullType) matcher) =
+ fun ta tb ->
+ X.all_bound (A.get_inherited ta) >&&>
+ match A.unwrap ta, tb with
+
+ (* cas general *)
+ | A.MetaType(ida,keep, inherited), typb ->
+ let max_min _ =
+ Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_type typb) in
+ X.envf keep inherited (ida, B.MetaTypeVal typb, max_min) (fun () ->
+ X.distrf_type ida typb >>= (fun ida typb ->
+ return (
+ A.MetaType(ida,keep, inherited) +> A.rewrap ta,
+ typb
+ ))
+ )
+ | unwrap, (qub, typb) ->
+ typeC ta typb >>= (fun ta typb ->
+ return (ta, (qub, typb))
+ )
+
+
+and (typeC: (A.typeC, Ast_c.typeC) matcher) =
+ fun ta tb ->
+ match A.unwrap ta, tb with
+ | A.BaseType (basea, signaopt), (B.BaseType baseb, ii) ->
+ (* In ii there is a list, sometimes of length 1 or 2 or 3.
+ * And even if in baseb we have a Signed Int, that does not mean
+ * that ii is of length 2, cos Signed is the default, so if in signa
+ * we have Signed explicitely ? we cant "accrocher" this mcode to
+ * something :( So for the moment when there is signed in cocci,
+ * we force that there is a signed in c too (done in pattern.ml).
+ *)
+ let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
+
+
+ (* handle some iso on type ? (cf complex C rule for possible implicit
+ casting) *)
+ (match term basea, baseb with
+ | A.VoidType, B.Void
+ | A.FloatType, B.FloatType (B.CFloat)
+ | A.DoubleType, B.FloatType (B.CDouble) ->
+ assert (signaopt = None);
+ let (ibaseb) = tuple_of_list1 ii in
+ tokenf basea ibaseb >>= (fun basea ibaseb ->
+ return (
+ (A.BaseType (basea, signaopt)) +> A.rewrap ta,
+ (B.BaseType baseb, [ibaseb])
+ ))
+
+ | A.CharType, B.IntType B.CChar when signaopt = None ->
+ let ibaseb = tuple_of_list1 ii in
+ tokenf basea ibaseb >>= (fun basea ibaseb ->
+ return (
+ (A.BaseType (basea, signaopt)) +> A.rewrap ta,
+ (B.BaseType (B.IntType B.CChar), [ibaseb])
+ ))
+
+ | A.CharType,B.IntType (B.Si (_sign, B.CChar2)) when signaopt <> None ->
+ let ibaseb = tuple_of_list1 iibaseb in
+ sign signaopt signbopt >>= (fun signaopt iisignbopt ->
+ tokenf basea ibaseb >>= (fun basea ibaseb ->
+ return (
+ (A.BaseType (basea, signaopt)) +> A.rewrap ta,
+ (B.BaseType (baseb), iisignbopt ++ [ibaseb])
+ )))
+
+ | A.ShortType, B.IntType (B.Si (_, B.CShort))
+ | A.IntType, B.IntType (B.Si (_, B.CInt))
+ | A.LongType, B.IntType (B.Si (_, B.CLong)) ->
+ (match iibaseb with
+ | [] ->
+ (* iso-by-presence ? *)
+ (* when unsigned int in SP, allow have just unsigned in C ? *)
+ if mcode_contain_plus (mcodekind basea)
+ then fail
+ else
+
+ sign signaopt signbopt >>= (fun signaopt iisignbopt ->
+ return (
+ (A.BaseType (basea, signaopt)) +> A.rewrap ta,
+ (B.BaseType (baseb), iisignbopt ++ [])
+ ))
+
+
+ | [x;y] ->
+ pr2_once
+ "warning: long int or short int not handled by ast_cocci";
+ fail
+
+ | [ibaseb] ->
+ sign signaopt signbopt >>= (fun signaopt iisignbopt ->
+ tokenf basea ibaseb >>= (fun basea ibaseb ->
+ return (
+ (A.BaseType (basea, signaopt)) +> A.rewrap ta,
+ (B.BaseType (baseb), iisignbopt ++ [ibaseb])
+ )))
+ | _ -> raise Impossible
+
+ )
+
+
+ | _, B.IntType (B.Si (_, B.CLongLong))
+ | _, B.FloatType B.CLongDouble
+ ->
+ pr2_once
+ "warning: long long or long double not handled by ast_cocci";
+ fail
+
+
+ | _, _ -> fail
+
+
+ )
+
+ | A.ImplicitInt (signa), (B.BaseType baseb, ii) ->
+ let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
+ (match iibaseb, baseb with
+ | [], B.IntType (B.Si (_sign, B.CInt)) ->
+ sign (Some signa) signbopt >>= (fun signaopt iisignbopt ->
+ match signaopt with
+ | None -> raise Impossible
+ | Some signa ->
+ return (
+ (A.ImplicitInt (signa)) +> A.rewrap ta,
+ (B.BaseType baseb, iisignbopt)
+ )
+ )
+ | _ -> fail
+ )
+
+
+
+ (* todo? iso with array *)
+ | A.Pointer (typa, iamult), (B.Pointer typb, ii) ->
+ let (ibmult) = tuple_of_list1 ii in
+ fullType typa typb >>= (fun typa typb ->
+ tokenf iamult ibmult >>= (fun iamult ibmult ->
+ return (
+ (A.Pointer (typa, iamult)) +> A.rewrap ta,
+ (B.Pointer typb, [ibmult])
+ )))
+
+ | A.FunctionType(allminus,tyaopt,lpa,paramsa,rpa),
+ (B.FunctionType(tyb, (paramsb, (isvaargs, iidotsb))), ii) ->
+
+ let (lpb, rpb) = tuple_of_list2 ii in
+ if isvaargs
+ then
+ pr2_once
+ ("Not handling well variable length arguments func. "^
+ "You have been warned");
+ tokenf lpa lpb >>= (fun lpa lpb ->
+ tokenf rpa rpb >>= (fun rpa rpb ->
+ fullType_optional_allminus allminus tyaopt tyb >>= (fun tyaopt tyb ->
+ parameters (seqstyle paramsa) (A.undots paramsa) paramsb >>=
+ (fun paramsaundots paramsb ->
+ let paramsa = redots paramsa paramsaundots in
+ return (
+ (A.FunctionType(allminus,tyaopt,lpa,paramsa,rpa) +> A.rewrap ta,
+ (B.FunctionType(tyb, (paramsb, (isvaargs, iidotsb))), [lpb;rpb])
+ )
+ )))))
+
+
+
+
+
+ | A.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a),
+ (B.ParenType t1, ii) ->
+ let (lp1b, rp1b) = tuple_of_list2 ii in
+ let (qu1b, t1b) = t1 in
+ (match t1b with
+ | B.Pointer t2, ii ->
+ let (starb) = tuple_of_list1 ii in
+ let (qu2b, t2b) = t2 in
+ (match t2b with
+ | B.FunctionType (tyb, (paramsb, (isvaargs, iidotsb))), ii ->
+ let (lp2b, rp2b) = tuple_of_list2 ii in
+
+ if isvaargs
+ then
+ pr2_once
+ ("Not handling well variable length arguments func. "^
+ "You have been warned");
+
+ fullType tya tyb >>= (fun tya tyb ->
+ tokenf lp1a lp1b >>= (fun lp1a lp1b ->
+ tokenf rp1a rp1b >>= (fun rp1a rp1b ->
+ tokenf lp2a lp2b >>= (fun lp2a lp2b ->
+ tokenf rp2a rp2b >>= (fun rp2a rp2b ->
+ tokenf stara starb >>= (fun stara starb ->
+ parameters (seqstyle paramsa) (A.undots paramsa) paramsb >>=
+ (fun paramsaundots paramsb ->
+ let paramsa = redots paramsa paramsaundots in
+
+ let t2 =
+ (qu2b,
+ (B.FunctionType (tyb, (paramsb, (isvaargs, iidotsb))),
+ [lp2b;rp2b]))
+ in
+ let t1 =
+ (qu1b,
+ (B.Pointer t2, [starb]))
+ in
+
+ return (
+ (A.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a))
+ +> A.rewrap ta,
+ (B.ParenType t1, [lp1b;rp1b])
+ )
+ )))))))
+
+
+
+ | _ -> fail
+ )
+ | _ -> fail
+ )
+
+
+
+ (* todo: handle the iso on optionnal size specifification ? *)
+ | A.Array (typa, ia1, eaopt, ia2), (B.Array (ebopt, typb), ii) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ fullType typa typb >>= (fun typa typb ->
+ option expression eaopt ebopt >>= (fun eaopt ebopt ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ (A.Array (typa, ia1, eaopt, ia2)) +> A.rewrap ta,
+ (B.Array (ebopt, typb), [ib1;ib2])
+ )))))
+
+
+ (* todo: could also match a Struct that has provided a name *)
+ (* This is for the case where the SmPL code contains "struct x", without
+ a definition. In this case, the name field is always present.
+ This case is also called from the case for A.StructUnionDef when
+ a name is present in the C code. *)
+ | A.StructUnionName(sua, Some sa), (B.StructUnionName (sub, sb), ii) ->
+ (* sa is now an ident, not an mcode, old: ... && (term sa) =$= sb *)
+ let (ib1, ib2) = tuple_of_list2 ii in
+ if equal_structUnion (term sua) sub
+ then
+ ident DontKnow sa (sb, ib2) >>= (fun sa (sb, ib2) ->
+ tokenf sua ib1 >>= (fun sua ib1 ->
+ return (
+ (A.StructUnionName (sua, Some sa)) +> A.rewrap ta,
+ (B.StructUnionName (sub, sb), [ib1;ib2])
+ )))
+ else fail
+
+
+ | A.StructUnionDef(ty, lba, declsa, rba),
+ (B.StructUnion (sub, sbopt, declsb), ii) ->
+
+ let (ii_sub_sb, lbb, rbb) =
+ match ii with
+ [iisub; lbb; rbb] -> (Common.Left iisub,lbb,rbb)
+ | [iisub; iisb; lbb; rbb] -> (Common.Right (iisub,iisb),lbb,rbb)
+ | _ -> failwith "list of length 3 or 4 expected" in
+
+ let process_type =
+ match (sbopt,ii_sub_sb) with
+ (None,Common.Left iisub) ->
+ (* the following doesn't reconstruct the complete SP code, just
+ the part that matched *)
+ let rec loop s =
+ match A.unwrap s with
+ A.Type(None,ty) ->
+ (match A.unwrap ty with
+ A.StructUnionName(sua, None) ->
+ tokenf sua iisub >>= (fun sua iisub ->
+ let ty =
+ A.Type(None,
+ A.StructUnionName(sua, None) +> A.rewrap ty)
+ +> A.rewrap s in
+ return (ty,[iisub]))
+ | _ -> fail)
+ | A.DisjType(disjs) ->
+ disjs +>
+ List.fold_left (fun acc disj -> acc >|+|> (loop disj)) fail
+ | _ -> fail in
+ loop ty
+
+ | (Some sb,Common.Right (iisub,iisb)) ->
+
+ (* build a StructUnionName from a StructUnion *)
+ let fake_su = B.nQ, (B.StructUnionName (sub, sb), [iisub;iisb]) in
+
+ fullType ty fake_su >>= (fun ty fake_su ->
+ match fake_su with
+ | _nQ, (B.StructUnionName (sub, sb), [iisub;iisb]) ->
+ return (ty, [iisub; iisb])
+ | _ -> raise Impossible)
+ | _ -> fail in
+
+ process_type
+ >>= (fun ty ii_sub_sb ->
+
+ tokenf lba lbb >>= (fun lba lbb ->
+ tokenf rba rbb >>= (fun rba rbb ->
+ struct_fields (A.undots declsa) declsb >>=(fun undeclsa declsb ->
+ let declsa = redots declsa undeclsa in
+
+ return (
+ (A.StructUnionDef(ty, lba, declsa, rba)) +> A.rewrap ta,
+ (B.StructUnion (sub, sbopt, declsb),ii_sub_sb@[lbb;rbb])
+ )))))
+
+
+ (* todo? handle isomorphisms ? because Unsigned Int can be match on a
+ * uint in the C code. But some CEs consists in renaming some types,
+ * so we don't want apply isomorphisms every time.
+ *)
+ | A.TypeName sa, (B.TypeName (sb,typb), ii) ->
+ let (isb) = tuple_of_list1 ii in
+ if (term sa) =$= sb
+ then
+ tokenf sa isb >>= (fun sa isb ->
+ return (
+ (A.TypeName sa) +> A.rewrap ta,
+ (B.TypeName (sb,typb), [isb])
+ ))
+ else fail
+
+ | _, (B.TypeOfExpr e, ii) -> fail
+ | _, (B.TypeOfType e, ii) -> fail
+
+ | _, _ -> fail
+
+(* todo: iso on sign, if not mentioned then free. tochange?
+ * but that require to know if signed int because explicit
+ * signed int, or because implicit signed int.
+ *)
+
+and sign signa signb =
+ match signa, signb with
+ | None, None -> return (None, [])
+ | Some signa, Some (signb, ib) ->
+ if equal_sign (term signa) signb
+ then tokenf signa ib >>= (fun signa ib ->
+ return (Some signa, [ib])
+ )
+ else fail
+ | _, _ -> fail
+
+
+and minusize_list iixs =
+ iixs +> List.fold_left (fun acc ii ->
+ acc >>= (fun xs ys ->
+ tokenf minusizer ii >>= (fun minus ii ->
+ return (minus::xs, ii::ys)
+ ))) (return ([],[]))
+ >>= (fun _xsminys ys ->
+ return ((), List.rev ys)
+ )
+
+and storage_optional_allminus allminus stoa (stob, iistob) =
+ (* "iso-by-absence" for storage, and return type. *)
+ X.optional_storage_flag (fun optional_storage ->
+ match stoa, stob with
+ | None, (stobis, inline) ->
+ let do_minus () =
+ if allminus
+ then
+ minusize_list iistob >>= (fun () iistob ->
+ return (None, (stob, iistob))
+ )
+ else return (None, (stob, iistob))
+ in
+
+ (match optional_storage, stobis with
+ | false, B.NoSto -> do_minus ()
+ | false, _ -> fail
+ | true, B.NoSto -> do_minus ()
+ | true, _ ->
+ if !Flag.show_misc
+ then pr2_once "USING optional_storage builtin isomorphism";
+ do_minus()
+ )
+
+ | Some x, ((stobis, inline)) ->
+ if equal_storage (term x) stobis
+ then
+ match iistob with
+ | [i1] ->
+ tokenf x i1 >>= (fun x i1 ->
+ return (Some x, ((stobis, inline), [i1]))
+ )
+ (* or if have inline ? have to do a split_storage_inline a la
+ * split_signb_baseb_ii *)
+ | _ -> raise Impossible
+ else fail
+ )
+
+
+
+
+
+and fullType_optional_allminus allminus tya retb =
+ match tya with
+ | None ->
+ if allminus
+ then
+ X.distrf_type minusizer retb >>= (fun _x retb ->
+ return (None, retb)
+ )
+
+ else return (None, retb)
+ | Some tya ->
+ fullType tya retb >>= (fun tya retb ->
+ return (Some tya, retb)
+ )
+
+
+
+(*---------------------------------------------------------------------------*)
+and compatible_type a (b,_local) =
+ let ok = return ((),()) in
+
+ let rec loop = function
+ | Type_cocci.BaseType (a, signa), (qua, (B.BaseType b,ii)) ->
+ (match a, b with
+ | Type_cocci.VoidType, B.Void ->
+ assert (signa = None);
+ ok
+ | Type_cocci.CharType, B.IntType B.CChar when signa = None ->
+ ok
+ | Type_cocci.CharType, B.IntType (B.Si (signb, B.CChar2)) ->
+ compatible_sign signa signb
+ | Type_cocci.ShortType, B.IntType (B.Si (signb, B.CShort)) ->
+ compatible_sign signa signb
+ | Type_cocci.IntType, B.IntType (B.Si (signb, B.CInt)) ->
+ compatible_sign signa signb
+ | Type_cocci.LongType, B.IntType (B.Si (signb, B.CLong)) ->
+ compatible_sign signa signb
+ | _, B.IntType (B.Si (signb, B.CLongLong)) ->
+ pr2_once "no longlong in cocci";
+ fail
+ | Type_cocci.FloatType, B.FloatType B.CFloat ->
+ assert (signa = None);
+ ok
+ | Type_cocci.DoubleType, B.FloatType B.CDouble ->
+ assert (signa = None);
+ ok
+ | _, B.FloatType B.CLongDouble ->
+ pr2_once "no longdouble in cocci";
+ fail
+ | Type_cocci.BoolType, _ -> failwith "no booltype in C"
+ | _ -> fail
+
+ )
+ | Type_cocci.Pointer a, (qub, (B.Pointer b, ii)) ->
+ loop (a,b)
+ | Type_cocci.FunctionPointer a, _ ->
+ failwith
+ "TODO: function pointer type doesn't store enough information to determine compatability"
+ | Type_cocci.Array a, (qub, (B.Array (eopt, b),ii)) ->
+ (* no size info for cocci *)
+ loop (a,b)
+ | Type_cocci.StructUnionName (sua, _, sa),
+ (qub, (B.StructUnionName (sub, sb),ii)) ->
+ if equal_structUnion_type_cocci sua sub && sa = sb
+ then ok
+ else fail
+
+ | Type_cocci.TypeName sa, (qub, (B.TypeName (sb,_typb), ii)) ->
+ if sa = sb
+ then ok
+ else fail
+
+ | Type_cocci.ConstVol (qua, a), (qub, b) ->
+ if (fst qub).B.const && (fst qub).B.volatile
+ then
+ begin
+ pr2_once ("warning: the type is both const & volatile but cocci " ^
+ "does not handle that");
+ fail
+ end
+ else
+ if
+ (match qua with
+ | Type_cocci.Const -> (fst qub).B.const
+ | Type_cocci.Volatile -> (fst qub).B.volatile
+ )
+ then loop (a,(Ast_c.nQ, b))
+ else fail
+
+ | Type_cocci.MetaType (ida,keep,inherited), typb ->
+ let max_min _ =
+ Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_type typb) in
+ X.envf keep inherited (A.make_mcode ida, B.MetaTypeVal typb, max_min)
+ (fun () -> ok
+ )
+
+ (* subtil: must be after the MetaType case *)
+ | a, (qub, (B.TypeName (sb,Some b), ii)) ->
+ (* kind of typedef iso *)
+ loop (a,b)
+
+
+
+
+
+ (* for metavariables of type expression *^* *)
+ | Type_cocci.Unknown , _ -> ok
+
+ | _ -> fail in
+ loop (a,b)
+
+and compatible_sign signa signb =
+ let ok = return ((),()) in
+ match signa, signb with
+ | None, B.Signed
+ | Some Type_cocci.Signed, B.Signed
+ | Some Type_cocci.Unsigned, B.UnSigned
+ -> ok
+ | _ -> fail
+
+
+and equal_structUnion_type_cocci a b =
+ match a, b with
+ | Type_cocci.Struct, B.Struct -> true
+ | Type_cocci.Union, B.Union -> true
+ | _, _ -> false
+
+
+
+(*---------------------------------------------------------------------------*)
+and inc_file (a, before_after) (b, h_rel_pos) =
+
+ let rec aux_inc (ass, bss) passed =
+ match ass, bss with
+ | [], [] -> true
+ | [A.IncDots], _ ->
+ let passed = List.rev passed in
+
+ (match before_after, !h_rel_pos with
+ | IncludeNothing, _ -> true
+ | IncludeMcodeBefore, Some x ->
+ List.mem passed (x.Ast_c.first_of)
+
+ | IncludeMcodeAfter, Some x ->
+ List.mem passed (x.Ast_c.last_of)
+
+ (* no info, maybe cos of a #include <xx.h> that was already in a .h *)
+ | _, None -> false
+ )
+
+ | (A.IncPath x)::xs, y::ys -> x = y && aux_inc (xs, ys) (x::passed)
+ | _ -> failwith "IncDots not in last place or other pb"
+
+ in
+
+ match a, b with
+ | A.Local ass, B.Local bss ->
+ aux_inc (ass, bss) []
+ | A.NonLocal ass, B.NonLocal bss ->
+ aux_inc (ass, bss) []
+ | _ -> false
+
+
+
+(*---------------------------------------------------------------------------*)
+
+and (define_params: sequence ->
+ (A.define_param list, (string B.wrap) B.wrap2 list) matcher) =
+ fun seqstyle eas ebs ->
+ match seqstyle with
+ | Unordered -> failwith "not handling ooo"
+ | Ordered ->
+ define_paramsbis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
+ return (eas, (Ast_c.unsplit_comma ebs_splitted))
+ )
+
+(* todo? facto code with argument and parameters ? *)
+and define_paramsbis = fun eas ebs ->
+ match eas, ebs with
+ | [], [] -> return ([], [])
+ | [], eb::ebs -> fail
+ | ea::eas, ebs ->
+ X.all_bound (A.get_inherited ea) >&&>
+ (match A.unwrap ea, ebs with
+ | A.DPdots (mcode), ys ->
+
+ (* '...' can take more or less the beginnings of the arguments *)
+ let startendxs = Common.zip (Common.inits ys) (Common.tails ys) in
+ startendxs +> List.fold_left (fun acc (startxs, endxs) ->
+ acc >||> (
+
+ (if startxs = []
+ then
+ if mcode_contain_plus (mcodekind mcode)
+ then fail
+ (* failwith "I have no token that I could accroche myself on" *)
+ else return (dots2metavar mcode, [])
+ else
+ (match Common.last startxs with
+ | Right _ -> fail
+ | Left _ ->
+ X.distrf_define_params (dots2metavar mcode) startxs
+ )
+ ) >>= (fun mcode startxs ->
+ let mcode = metavar2dots mcode in
+ define_paramsbis eas endxs >>= (fun eas endxs ->
+ return (
+ (A.DPdots (mcode) +> A.rewrap ea) ::eas,
+ startxs ++ endxs
+ )))
+ )
+ ) fail
+
+ | A.DPComma ia1, Right ii::ebs ->
+ let ib1 = tuple_of_list1 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ define_paramsbis eas ebs >>= (fun eas ebs ->
+ return (
+ (A.DPComma ia1 +> A.rewrap ea)::eas,
+ (Right [ib1])::ebs
+ )
+ ))
+
+ | A.DPComma ia1, ebs ->
+ if mcode_contain_plus (mcodekind ia1)
+ then fail
+ else
+ (define_paramsbis eas ebs) (* try optional comma trick *)
+
+ | (A.OptDParam _ | A.UniqueDParam _), _ ->
+ failwith "handling Opt/Unique for define parameters"
+
+ | A.DPcircles (_), ys -> raise Impossible (* in Ordered mode *)
+
+ | A.DParam ida, (Left (idb, ii))::ebs ->
+ let ib1 = tuple_of_list1 ii in
+ ident DontKnow ida (idb, ib1) >>= (fun ida (idb, ib1) ->
+ define_paramsbis eas ebs >>= (fun eas ebs ->
+ return (
+ (A.DParam ida)+> A.rewrap ea :: eas,
+ (Left (idb, [ib1]))::ebs
+ )))
+
+ | _unwrapx, (Right y)::ys -> raise Impossible
+ | _unwrapx, [] -> fail
+ )
+
+
+
+(*****************************************************************************)
+(* Entry points *)
+(*****************************************************************************)
+
+(* no global solution for positions here, because for a statement metavariable
+we want a MetaStmtVal, and for the others, it's not clear what we want *)
+
+let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
+ fun re node ->
+ let rewrap x =
+ x >>= (fun a b -> return (A.rewrap re a, F.rewrap node b))
+ in
+ X.all_bound (A.get_inherited re) >&&>
+
+ rewrap (
+ match A.unwrap re, F.unwrap node with
+
+ (* note: the order of the clauses is important. *)
+
+ | _, F.Enter | _, F.Exit | _, F.ErrorExit -> fail2()
+
+ (* the metaRuleElem contains just '-' information. We dont need to add
+ * stuff in the environment. If we need stuff in environment, because
+ * there is a + S somewhere, then this will be done via MetaStmt, not
+ * via MetaRuleElem.
+ * Can match TrueNode/FalseNode/... so must be placed before those cases.
+ *)
+
+ | A.MetaRuleElem(mcode,keep,inherited), unwrap_node ->
+ let default = A.MetaRuleElem(mcode,keep,inherited), unwrap_node in
+ (match unwrap_node with
+ | F.CaseNode _
+ | F.TrueNode | F.FalseNode | F.AfterNode | F.FallThroughNode
+ | F.InLoopNode ->
+ if X.mode = PatternMode
+ then return default
+ else
+ if mcode_contain_plus (mcodekind mcode)
+ then failwith "try add stuff on fake node"
+ (* minusize or contextize a fake node is ok *)
+ else return default
+
+ | F.EndStatement None ->
+ if X.mode = PatternMode then return default
+ else
+ (* DEAD CODE NOW ? only useful in -no_cocci_vs_c_3 ?
+ if mcode_contain_plus (mcodekind mcode)
+ then
+ let fake_info = Ast_c.fakeInfo() in
+ distrf distrf_node (mcodekind mcode)
+ (F.EndStatement (Some fake_info))
+ else return unwrap_node
+ *)
+ raise Todo
+
+ | F.EndStatement (Some i1) ->
+ tokenf mcode i1 >>= (fun mcode i1 ->
+ return (
+ A.MetaRuleElem (mcode,keep, inherited),
+ F.EndStatement (Some i1)
+ ))
+
+ | F.FunHeader _ ->
+ if X.mode = PatternMode then return default
+ else failwith "a MetaRuleElem can't transform a headfunc"
+ | _n ->
+ if X.mode = PatternMode then return default
+ else
+ X.distrf_node (generalize_mcode mcode) node >>= (fun mcode node ->
+ return (
+ A.MetaRuleElem(mcode,keep, inherited),
+ F.unwrap node
+ ))
+ )
+
+
+ (* rene cant have found that a state containing a fake/exit/... should be
+ * transformed
+ * TODO: and F.Fake ?
+ *)
+ | _, F.EndStatement _ | _, F.CaseNode _
+ | _, F.TrueNode | _, F.FalseNode | _, F.AfterNode | _, F.FallThroughNode
+ | _, F.InLoopNode
+ -> fail2()
+
+ (* really ? diff between pattern.ml and transformation.ml *)
+ | _, F.Fake -> fail2()
+
+
+ (* cas general: a Meta can match everything. It matches only
+ * "header"-statement. We transform only MetaRuleElem, not MetaStmt.
+ * So can't have been called in transform.
+ *)
+ | A.MetaStmt (ida,keep,metainfoMaybeTodo,inherited), F.Decl(_) -> fail
+
+ | A.MetaStmt (ida,keep,metainfoMaybeTodo,inherited), unwrap_node ->
+ (* todo: should not happen in transform mode *)
+
+ (match Control_flow_c.extract_fullstatement node with
+ | Some stb ->
+ let max_min _ =
+ Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_stmt stb) in
+ X.envf keep inherited (ida, Ast_c.MetaStmtVal stb, max_min)
+ (fun () ->
+ (* no need tag ida, we can't be called in transform-mode *)
+ return (
+ A.MetaStmt (ida, keep, metainfoMaybeTodo, inherited),
+ unwrap_node
+ )
+ )
+ | None -> fail
+ )
+
+ (* not me?: *)
+ | A.MetaStmtList _, _ ->
+ failwith "not handling MetaStmtList"
+
+ | A.TopExp ea, F.DefineExpr eb ->
+ expression ea eb >>= (fun ea eb ->
+ return (
+ A.TopExp ea,
+ F.DefineExpr eb
+ ))
+
+ | A.TopExp ea, F.DefineType eb ->
+ (match A.unwrap ea with
+ A.TypeExp(ft) ->
+ fullType ft eb >>= (fun ft eb ->
+ return (
+ A.TopExp (A.rewrap ea (A.TypeExp(ft))),
+ F.DefineType eb
+ ))
+ | _ -> fail)
+
+
+
+ (* It is important to put this case before the one that fails because
+ * of the lack of the counter part of a C construct in SmPL (for instance
+ * there is not yet a CaseRange in SmPL). Even if SmPL don't handle
+ * yet certain constructs, those constructs may contain expression
+ * that we still want and can transform.
+ *)
+
+ | A.Exp exp, nodeb ->
+
+ (* kind of iso, initialisation vs affectation *)
+ let node =
+ match A.unwrap exp, nodeb with
+ | A.Assignment (ea, op, eb, true), F.Decl decl ->
+ initialisation_to_affectation decl +> F.rewrap node
+ | _ -> node
+ in
+
+
+ (* Now keep fullstatement inside the control flow node,
+ * so that can then get in a MetaStmtVar the fullstatement to later
+ * pp back when the S is in a +. But that means that
+ * Exp will match an Ifnode even if there is no such exp
+ * inside the condition of the Ifnode (because the exp may
+ * be deeper, in the then branch). So have to not visit
+ * all inside a node anymore.
+ *
+ * update: j'ai choisi d'accrocher au noeud du CFG Ã la
+ * fois le fullstatement et le partialstatement et appeler le
+ * visiteur que sur le partialstatement.
+ *)
+ let expfn =
+ match Ast_cocci.get_pos re with
+ | None -> expression
+ | Some pos ->
+ (fun ea eb ->
+ let (max,min) =
+ Lib_parsing_c.max_min_by_pos (Lib_parsing_c.ii_of_expr eb) in
+ let keep = Type_cocci.Unitary in
+ let inherited = false in
+ let max_min _ = failwith "no pos" in
+ X.envf keep inherited (pos, B.MetaPosVal (min,max), max_min)
+ (fun () ->
+ expression ea eb
+ )
+ )
+ in
+ X.cocciExp expfn exp node >>= (fun exp node ->
+ return (
+ A.Exp exp,
+ F.unwrap node
+ )
+ )
+
+
+
+ | A.Ty ty, nodeb ->
+ X.cocciTy fullType ty node >>= (fun ty node ->
+ return (
+ A.Ty ty,
+ F.unwrap node
+ )
+ )
+
+
+ | A.FunHeader (mckstart, allminus, fninfoa, ida, oparen, paramsa, cparen),
+ F.FunHeader ((idb, (retb, (paramsb, (isvaargs, iidotsb))), stob), ii) ->
+
+ (* fninfoa records the order in which the SP specified the various
+ information, but this isn't taken into account in the matching.
+ Could this be a problem for transformation? *)
+ let stoa =
+ match
+ List.filter (function A.FStorage(s) -> true | _ -> false) fninfoa
+ with [A.FStorage(s)] -> Some s | _ -> None in
+ let tya =
+ match List.filter (function A.FType(s) -> true | _ -> false) fninfoa
+ with [A.FType(t)] -> Some t | _ -> None in
+
+ (match List.filter (function A.FInline(i) -> true | _ -> false) fninfoa
+ with [A.FInline(i)] -> failwith "not checking inline" | _ -> ());
+
+ (match List.filter (function A.FAttr(a) -> true | _ -> false) fninfoa
+ with [A.FAttr(a)] -> failwith "not checking attributes" | _ -> ());
+
+ (match ii with
+ | iidb::ioparenb::icparenb::iifakestart::iistob ->
+
+ (* maybe important to put ident as the first tokens to transform.
+ * It's related to transform_proto. So don't change order
+ * between the >>=.
+ *)
+ ident LocalFunction ida (idb, iidb) >>= (fun ida (idb, iidb) ->
+ X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
+ tokenf oparen ioparenb >>= (fun oparen ioparenb ->
+ tokenf cparen icparenb >>= (fun cparen icparenb ->
+ parameters (seqstyle paramsa)
+ (A.undots paramsa) paramsb >>=
+ (fun paramsaundots paramsb ->
+ let paramsa = redots paramsa paramsaundots in
+ storage_optional_allminus allminus
+ stoa (stob, iistob) >>= (fun stoa (stob, iistob) ->
+ (
+ if isvaargs
+ then
+ pr2_once
+ ("Not handling well variable length arguments func. "^
+ "You have been warned");
+ if allminus
+ then minusize_list iidotsb
+ else return ((),iidotsb)
+ ) >>= (fun () iidotsb ->
+
+ fullType_optional_allminus allminus tya retb >>= (fun tya retb ->
+
+ let fninfoa =
+ (match stoa with Some st -> [A.FStorage st] | None -> []) ++
+ (match tya with Some t -> [A.FType t] | None -> [])
+
+ in
+
+ return (
+ A.FunHeader(mckstart,allminus,fninfoa,ida,oparen,
+ paramsa,cparen),
+ F.FunHeader ((idb, (retb, (paramsb, (isvaargs, iidotsb))),
+ stob),
+ iidb::ioparenb::icparenb::iifakestart::iistob)
+ )
+ ))))))))
+ | _ -> raise Impossible
+ )
+
+
+
+
+
+
+ | A.Decl (mckstart,allminus,decla), F.Decl declb ->
+ declaration (mckstart,allminus,decla) declb >>=
+ (fun (mckstart,allminus,decla) declb ->
+ return (
+ A.Decl (mckstart,allminus,decla),
+ F.Decl declb
+ ))
+
+
+ | A.SeqStart mcode, F.SeqStart (st, level, i1) ->
+ tokenf mcode i1 >>= (fun mcode i1 ->
+ return (
+ A.SeqStart mcode,
+ F.SeqStart (st, level, i1)
+ ))
+
+ | A.SeqEnd mcode, F.SeqEnd (level, i1) ->
+ tokenf mcode i1 >>= (fun mcode i1 ->
+ return (
+ A.SeqEnd mcode,
+ F.SeqEnd (level, i1)
+ ))
+
+ | A.ExprStatement (ea, ia1), F.ExprStatement (st, (Some eb, ii)) ->
+ let ib1 = tuple_of_list1 ii in
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ return (
+ A.ExprStatement (ea, ia1),
+ F.ExprStatement (st, (Some eb, [ib1]))
+ )
+ ))
+
+
+ | A.IfHeader (ia1,ia2, ea, ia3), F.IfHeader (st, (eb,ii)) ->
+ let (ib1, ib2, ib3) = tuple_of_list3 ii in
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ return (
+ A.IfHeader (ia1, ia2, ea, ia3),
+ F.IfHeader (st, (eb,[ib1;ib2;ib3]))
+ )))))
+
+ | A.Else ia, F.Else ib ->
+ tokenf ia ib >>= (fun ia ib ->
+ return (A.Else ia, F.Else ib)
+ )
+
+ | A.WhileHeader (ia1, ia2, ea, ia3), F.WhileHeader (st, (eb, ii)) ->
+ let (ib1, ib2, ib3) = tuple_of_list3 ii in
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ return (
+ A.WhileHeader (ia1, ia2, ea, ia3),
+ F.WhileHeader (st, (eb, [ib1;ib2;ib3]))
+ )))))
+
+ | A.DoHeader ia, F.DoHeader (st, ib) ->
+ tokenf ia ib >>= (fun ia ib ->
+ return (
+ A.DoHeader ia,
+ F.DoHeader (st, ib)
+ ))
+ | A.WhileTail (ia1,ia2,ea,ia3,ia4), F.DoWhileTail (eb, ii) ->
+ let (ib1, ib2, ib3, ib4) = tuple_of_list4 ii in
+ expression ea eb >>= (fun ea eb ->
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ tokenf ia4 ib4 >>= (fun ia4 ib4 ->
+ return (
+ A.WhileTail (ia1,ia2,ea,ia3,ia4),
+ F.DoWhileTail (eb, [ib1;ib2;ib3;ib4])
+ ))))))
+ | A.IteratorHeader (ia1, ia2, eas, ia3), F.MacroIterHeader (st, ((s,ebs),ii))
+ ->
+ let (ib1, ib2, ib3) = tuple_of_list3 ii in
+
+ ident DontKnow ia1 (s, ib1) >>= (fun ia1 (s, ib1) ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
+ let eas = redots eas easundots in
+ return (
+ A.IteratorHeader (ia1, ia2, eas, ia3),
+ F.MacroIterHeader (st, ((s,ebs), [ib1;ib2;ib3]))
+ )))))
+
+
+
+ | A.ForHeader (ia1, ia2, ea1opt, ia3, ea2opt, ia4, ea3opt, ia5),
+ F.ForHeader (st, (((eb1opt,ib3s), (eb2opt,ib4s), (eb3opt,ib4vide)), ii))
+ ->
+ assert (null ib4vide);
+ let (ib1, ib2, ib5) = tuple_of_list3 ii in
+ let ib3 = tuple_of_list1 ib3s in
+ let ib4 = tuple_of_list1 ib4s in
+
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ tokenf ia4 ib4 >>= (fun ia4 ib4 ->
+ tokenf ia5 ib5 >>= (fun ia5 ib5 ->
+ option expression ea1opt eb1opt >>= (fun ea1opt eb1opt ->
+ option expression ea2opt eb2opt >>= (fun ea2opt eb2opt ->
+ option expression ea3opt eb3opt >>= (fun ea3opt eb3opt ->
+ return (
+ A.ForHeader (ia1, ia2, ea1opt, ia3, ea2opt, ia4, ea3opt, ia5),
+ F.ForHeader (st, (((eb1opt,[ib3]), (eb2opt,[ib4]), (eb3opt,[])),
+ [ib1;ib2;ib5]))
+
+ )))))))))
+
+
+ | A.SwitchHeader(ia1,ia2,ea,ia3), F.SwitchHeader (st, (eb,ii)) ->
+ let (ib1, ib2, ib3) = tuple_of_list3 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ tokenf ia3 ib3 >>= (fun ia3 ib3 ->
+ expression ea eb >>= (fun ea eb ->
+ return (
+ A.SwitchHeader(ia1,ia2,ea,ia3),
+ F.SwitchHeader (st, (eb,[ib1;ib2;ib3]))
+ )))))
+
+ | A.Break (ia1, ia2), F.Break (st, ((),ii)) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ A.Break (ia1, ia2),
+ F.Break (st, ((),[ib1;ib2]))
+ )))
+
+ | A.Continue (ia1, ia2), F.Continue (st, ((),ii)) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ A.Continue (ia1, ia2),
+ F.Continue (st, ((),[ib1;ib2]))
+ )))
+
+ | A.Return (ia1, ia2), F.Return (st, ((),ii)) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ return (
+ A.Return (ia1, ia2),
+ F.Return (st, ((),[ib1;ib2]))
+ )))
+
+ | A.ReturnExpr (ia1, ea, ia2), F.ReturnExpr (st, (eb, ii)) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ tokenf ia1 ib1 >>= (fun ia1 ib1 ->
+ tokenf ia2 ib2 >>= (fun ia2 ib2 ->
+ expression ea eb >>= (fun ea eb ->
+ return (
+ A.ReturnExpr (ia1, ea, ia2),
+ F.ReturnExpr (st, (eb, [ib1;ib2]))
+ ))))
+
+
+
+ | A.Include(incla,filea), F.Include ((fileb, ii), (h_rel_pos, inifdef)) ->
+
+ let include_requirment =
+ match mcodekind incla, mcodekind filea with
+ | A.CONTEXT (_, A.BEFORE _), _ ->
+ IncludeMcodeBefore
+ | _, A.CONTEXT (_, A.AFTER _) ->
+ IncludeMcodeAfter
+ | _ ->
+ IncludeNothing
+ in
+
+ let (inclb, iifileb) = tuple_of_list2 ii in
+ if inc_file (term filea, include_requirment) (fileb, h_rel_pos)
+ then
+ tokenf incla inclb >>= (fun incla inclb ->
+ tokenf filea iifileb >>= (fun filea iifileb ->
+ return (
+ A.Include(incla, filea),
+ F.Include ((fileb, [inclb;iifileb]), (h_rel_pos, inifdef))
+ )))
+ else fail
+
+
+
+ | A.DefineHeader(definea,ida,params), F.DefineHeader ((idb, ii), defkind) ->
+ let (defineb, iidb, ieol) = tuple_of_list3 ii in
+ ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
+ tokenf definea defineb >>= (fun definea defineb ->
+ (match A.unwrap params, defkind with
+ | A.NoParams, B.DefineVar ->
+ return (
+ A.NoParams +> A.rewrap params,
+ B.DefineVar
+ )
+ | A.DParams(lpa,eas,rpa), (B.DefineFunc (ebs, ii)) ->
+ let (lpb, rpb) = tuple_of_list2 ii in
+ tokenf lpa lpb >>= (fun lpa lpb ->
+ tokenf rpa rpb >>= (fun rpa rpb ->
+
+ define_params (seqstyle eas) (A.undots eas) ebs >>=
+ (fun easundots ebs ->
+ let eas = redots eas easundots in
+ return (
+ A.DParams (lpa,eas,rpa) +> A.rewrap params,
+ B.DefineFunc (ebs,[lpb;rpb])
+ )
+ )))
+ | _ -> fail
+ ) >>= (fun params defkind ->
+ return (
+ A.DefineHeader (definea, ida, params),
+ F.DefineHeader ((idb,[defineb;iidb;ieol]),defkind)
+ ))
+ ))
+
+
+ | A.Default(def,colon), F.Default (st, ((),ii)) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ tokenf def ib1 >>= (fun def ib1 ->
+ tokenf colon ib2 >>= (fun colon ib2 ->
+ return (
+ A.Default(def,colon),
+ F.Default (st, ((),[ib1;ib2]))
+ )))
+
+
+
+ | A.Case(case,ea,colon), F.Case (st, (eb,ii)) ->
+ let (ib1, ib2) = tuple_of_list2 ii in
+ tokenf case ib1 >>= (fun case ib1 ->
+ expression ea eb >>= (fun ea eb ->
+ tokenf colon ib2 >>= (fun colon ib2 ->
+ return (
+ A.Case(case,ea,colon),
+ F.Case (st, (eb,[ib1;ib2]))
+ ))))
+
+ (* only occurs in the predicates generated by asttomember *)
+ | A.DisjRuleElem eas, _ ->
+ (eas +>
+ List.fold_left (fun acc ea -> acc >|+|> (rule_elem_node ea node)) fail)
+ >>= (fun ea eb -> return (A.unwrap ea,F.unwrap eb))
+
+ | _, F.ExprStatement (_, (None, ii)) -> fail (* happen ? *)
+
+ | A.Label(id,dd), F.Label (st,(s,ii)) ->
+ let (ib1,ib2) = tuple_of_list2 ii in
+ let (string_of_id,rebuild) =
+ match A.unwrap id with
+ A.Id(s) -> (s,function s -> A.rewrap id (A.Id(s)))
+ | _ -> failwith "labels with metavariables not supported" in
+ if (term string_of_id) =$= s
+ then
+ tokenf string_of_id ib1 >>= (fun string_of_id ib1 ->
+ tokenf dd ib2 >>= (fun dd ib2 ->
+ return (
+ A.Label(rebuild string_of_id,dd),
+ F.Label (st,(s,[ib1;ib2]))
+ )))
+ else fail
+
+ | A.Goto(goto,id,sem), F.Goto (st,(s,ii)) ->
+ let (ib1,ib2,ib3) = tuple_of_list3 ii in
+ tokenf goto ib1 >>= (fun goto ib1 ->
+ ident DontKnow id (s, ib2) >>= (fun id (s, ib2) ->
+ tokenf sem ib3 >>= (fun sem ib3 ->
+ return(
+ A.Goto(goto,id,sem),
+ F.Goto (st,(s,[ib1;ib2;ib3]))
+ ))))
+
+ (* have not a counter part in coccinelle, for the moment *)
+ (* todo?: print a warning at least ? *)
+ | _, F.CaseRange _
+ | _, F.Asm _
+ | _, F.Ifdef _
+ | _, F.MacroTop _
+ -> fail2()
+
+
+ | _, _ -> fail
+ )
+end
+
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Common
+
+open Ograph_extended
+
+module F = Control_flow_c
+
+(*****************************************************************************)
+(* Debugging functions *)
+(*****************************************************************************)
+let show_or_not_predicate pred =
+ if !Flag_engine.debug_engine then begin
+ indent_do (fun () ->
+ adjust_pp_with_indent_and_header "labeling: pred = " (fun () ->
+ Pretty_print_engine.pp_predicate pred;
+ );
+ )
+ end
+
+let show_or_not_nodes nodes =
+ if !Flag_engine.debug_engine then begin
+ indent_do (fun () ->
+ adjust_pp_with_indent_and_header "labeling: result = " (fun () ->
+ Common.pp_do_in_box (fun () ->
+ pp "{";
+ Common.print_between
+ (fun () -> pp ";"; Format.print_cut())
+ (fun (nodei, (_predTODO, subst)) ->
+ Format.print_int nodei;
+ Common.pp_do_in_box (fun () ->
+ Pretty_print_engine.pp_binding2_ctlsubst subst
+ )
+ ) nodes;
+ pp "}";
+ );
+ )
+ )
+ end
+
+let show_isos rule_elem =
+ match Ast_cocci.get_isos rule_elem with
+ [] -> ()
+ | isos ->
+ let line = Ast_cocci.get_line rule_elem in
+ Printf.printf "rule elem: ";
+ Pretty_print_cocci.rule_elem "" rule_elem;
+ Format.print_newline();
+ List.iter
+ (function (nm,x) ->
+ Printf.printf " iso: %s(%d): " nm line;
+ Pretty_print_cocci.pp_print_anything x;
+ Format.print_newline())
+ isos
+
+(*****************************************************************************)
+(* Labeling function *)
+(*****************************************************************************)
+let (-->) x v = Ast_ctl.Subst (x,v);;
+
+(* Take list of predicate and for each predicate returns where in the
+ * control flow it matches, and the set of subsitutions for this match.
+ *)
+let (labels_for_ctl: string list (* dropped isos *) ->
+ (nodei * F.node) list -> Lib_engine.metavars_binding ->
+ Lib_engine.label_ctlcocci) =
+ fun dropped_isos nodes binding ->
+
+ (fun p ->
+ show_or_not_predicate p;
+
+ let nodes' = nodes +> List.map (fun (nodei, node) ->
+ (* todo? put part of this code in pattern ? *)
+ (match p, F.unwrap node with
+ | Lib_engine.Paren s, (F.SeqStart (_, bracelevel, _)) ->
+ let make_var x = ("",i_to_s x) in
+ [(nodei, (p,[(s --> (Lib_engine.ParenVal (make_var bracelevel)))]))]
+ | Lib_engine.Paren s, (F.SeqEnd (bracelevel, _)) ->
+ let make_var x = ("",i_to_s x) in
+ [(nodei, (p,[(s --> (Lib_engine.ParenVal (make_var bracelevel)))]))]
+ | Lib_engine.Paren _, _ -> []
+ | Lib_engine.Label s, _ ->
+ let labels = F.extract_labels node in
+ [(nodei, (p,[(s --> (Lib_engine.LabelVal labels))]))]
+ | Lib_engine.BCLabel s, _ ->
+ (match F.extract_bclabels node with
+ [] -> [] (* null for all nodes that are not break or continue *)
+ | labels ->
+ [(nodei, (p,[(s --> (Lib_engine.LabelVal labels))]))])
+ | Lib_engine.PrefixLabel s, _ ->
+ let labels = F.extract_labels node in
+ let prefixes = Common.inits labels +> Common.tail in
+ prefixes +> List.map (fun prefixlabels ->
+ (nodei, (p,[(s --> (Lib_engine.LabelVal prefixlabels))]))
+ )
+
+ | Lib_engine.Match (re), _unwrapnode ->
+ let substs =
+ Pattern3.match_re_node dropped_isos re node binding
+ +> List.map (fun (re', subst) ->
+ Lib_engine.Match (re'), subst
+ )
+ in
+ substs +> List.map (fun (p', subst) ->
+ (nodei,
+ (p',
+ subst +> List.map (fun (s, meta) ->
+ s --> Lib_engine.NormalMetaVal meta
+ ))))
+
+ | Lib_engine.InLoop, F.InLoopNode -> [nodei, (p,[])]
+ | Lib_engine.TrueBranch , F.TrueNode -> [nodei, (p,[])]
+ | Lib_engine.FalseBranch, F.FalseNode -> [nodei, (p,[])]
+ | Lib_engine.After, F.AfterNode -> [nodei, (p,[])]
+ | Lib_engine.FallThrough, F.FallThroughNode -> [nodei,(p,[])]
+ | Lib_engine.FunHeader, F.FunHeader _ -> [nodei, (p,[])]
+ | Lib_engine.Top, F.TopNode -> [nodei, (p,[])]
+ | Lib_engine.Exit, F.Exit -> [nodei, (p,[])]
+ | Lib_engine.ErrorExit, F.ErrorExit -> [nodei, (p,[])]
+ | Lib_engine.Goto, F.Goto(_,_) -> [nodei, (p,[])]
+
+ | Lib_engine.InLoop , _ -> []
+ | Lib_engine.TrueBranch , _ -> []
+ | Lib_engine.FalseBranch, _ -> []
+ | Lib_engine.After, _ -> []
+ | Lib_engine.FallThrough, _ -> []
+ | Lib_engine.FunHeader, _ -> []
+ | Lib_engine.Top, _ -> []
+ | Lib_engine.Exit, _ -> []
+ | Lib_engine.ErrorExit, _ -> []
+ | Lib_engine.Goto, _ -> []
+
+ | Lib_engine.BindGood s, _ -> [(nodei, (p,[(s --> Lib_engine.GoodVal)]))]
+ | Lib_engine.BindBad s, _ -> [(nodei, (p,[(s --> Lib_engine.BadVal)]))]
+ | Lib_engine.FakeBrace, _ ->
+ if F.extract_is_fake node then [nodei, (p,[])] else []
+
+ | Lib_engine.Return, node ->
+ (match node with
+ (* todo? should match the Exit code ?
+ * todo: one day try also to match the special function
+ * such as panic();
+ *)
+ | F.Return _ -> [nodei, (p,[])]
+ | F.ReturnExpr _ -> [nodei, (p,[])]
+ | _ -> []
+ )
+ )
+ ) +> List.concat
+ in
+
+ show_or_not_nodes nodes';
+ nodes'
+ )
+
+(*****************************************************************************)
+(* Some fix flow, for CTL, for unparse *)
+(*****************************************************************************)
+(* could erase info on nodes, and edge, because they are not used by rene *)
+let (control_flow_for_ctl: F.cflow -> ('a, 'b) ograph_mutable) =
+ fun cflow -> cflow
+
+
+
+(* Just make the final node of the control flow loop over itself.
+ * It seems that one hypothesis of the SAT algorithm is that each node as at
+ * least a successor.
+ *
+ * update: do same for errorexit node.
+ *
+ * update: also erase the fake nodes (and adjust the edges accordingly),
+ * so that AX in CTL can now work.
+ * Indeed, Ã la fin de la branche then (et else), on devrait aller directement
+ * au suivant du endif, sinon si ecrit if(1) { foo(); }; bar();
+ * sans '...' entre le if et bar(), alors ca matchera pas car le CTL
+ * generera un AX bar() qui il tombera d'abord sur le [endif] :(
+ * Mais chiant de changer l'algo de generation, marche pas tres bien avec
+ * ma facon de faire recursive et compositionnel.
+ * => faire une fonction qui applique des fixes autour de ce control flow,
+ * comme ca passe un bon flow a rene, mais garde un flow a moi pour pouvoir
+ * facilement generate back the ast.
+ * alt: faire un wrapper autourde mon graphe pour lui passer dans le module CFG
+ * une fonction qui passe a travers les Fake, mais bof.
+ *
+ * update: also make loop the deadcode nodes, the one that have
+ * no predecessor.
+ *)
+let (fix_flow_ctl2: F.cflow -> F.cflow) = fun flow ->
+ let g = ref flow in
+
+ let topi = F.first_node !g in
+ !g#add_arc ((topi, topi), F.Direct);
+
+ (* for the #define CFG who have no Exit but have at least a EndNode *)
+ (try
+ let endi = F.find_node (fun x -> x = F.EndNode) !g in
+ !g#add_arc ((endi, endi), F.Direct);
+ with Not_found -> ()
+ );
+
+ (* for the regular functions *)
+ (try
+ let exitnodei = F.find_node (fun x -> x = F.Exit) !g in
+ let errornodei = F.find_node (fun x -> x = F.ErrorExit) !g in
+
+ !g#add_arc ((exitnodei, exitnodei), F.Direct);
+
+ if null ((!g#successors errornodei)#tolist) &&
+ null ((!g#predecessors errornodei)#tolist)
+ then !g#del_node errornodei
+ else !g#add_arc ((errornodei, errornodei), F.Direct);
+ with Not_found -> ()
+ );
+
+ let fake_nodes = !g#nodes#tolist +> List.filter (fun (nodei, node) ->
+ match F.unwrap node with
+ | F.CaseNode _
+ | F.Enter
+ (*| F.Fake*) (* [endif], [endswitch], ... *)
+ -> true
+ | _ -> false
+ ) in
+
+ fake_nodes +> List.iter (fun (nodei, node) -> F.remove_one_node nodei !g);
+
+ (* even when have deadcode, julia want loop over those nodes *)
+ !g#nodes#tolist +> List.iter (fun (nodei, node) ->
+ if (!g#predecessors nodei)#null
+ then begin
+ let fakei = !g#add_node (F.mk_node F.Fake [] [] "DEADCODELOOP") in
+ !g#add_arc ((fakei, nodei), F.Direct);
+ !g#add_arc ((fakei, fakei), F.Direct);
+ end
+ );
+
+ !g#nodes#tolist +> List.iter (fun (nodei, node) ->
+ assert (List.length ((!g#successors nodei)#tolist) >= 1);
+ (* no: && List.length ((!g#predecessors nodei)#tolist) >= 1
+ because the enter node at least have no predecessors *)
+ );
+
+ !g
+let fix_flow_ctl a =
+ Common.profile_code "fix_flow" (fun () -> fix_flow_ctl2 a)
+
+
+
+
+
+(*****************************************************************************)
+(* subtil: the label must operate on newflow, not (old) cflow
+ * update: now I supposed that we give me a fixed_flow
+ *)
+let model_for_ctl dropped_isos cflow binding =
+ let newflow = cflow (* old: fix_flow_ctl (control_flow_for_ctl cflow) *) in
+ let labels = labels_for_ctl dropped_isos (newflow#nodes#tolist) binding in
+ let states = List.map fst newflow#nodes#tolist in
+ newflow, labels, states
+
+
+(*****************************************************************************)
+
+module PRED =
+ struct
+ type t = Lib_engine.predicate
+ let print_predicate x =
+ Pretty_print_cocci.print_plus_flag := false;
+ Pretty_print_cocci.print_minus_flag := false;
+ Pretty_print_engine.pp_predicate x
+ end
+
+module ENV =
+ struct
+ type value = Lib_engine.metavar_binding_kind2
+ type mvar = Ast_cocci.meta_name
+ let eq_mvar x x' = x = x'
+ let eq_val v v' =
+ (* v = v' *)
+ match (v,v') with
+ (Lib_engine.NormalMetaVal(Ast_c.MetaPosVal(min1,max1)),
+ Lib_engine.NormalMetaVal(Ast_c.MetaPosVal(min2,max2))) ->
+ ((min1 <= min2) && (max1 >= max2)) or
+ ((min2 <= min1) && (max2 >= max1))
+ | (Lib_engine.NormalMetaVal(Ast_c.MetaTypeVal a),
+ Lib_engine.NormalMetaVal(Ast_c.MetaTypeVal b)) ->
+ C_vs_c.eq_type a b
+ | _ -> v = v'
+ let merge_val v v' = (* values guaranteed to be compatible *)
+ (* v *)
+ match (v,v') with
+ (Lib_engine.NormalMetaVal(Ast_c.MetaPosVal(min1,max1)),
+ Lib_engine.NormalMetaVal(Ast_c.MetaPosVal(min2,max2))) ->
+ if (min1 <= min2) && (max1 >= max2)
+ then Lib_engine.NormalMetaVal(Ast_c.MetaPosVal(min1,max1))
+ else
+ if (min2 <= min1) && (max2 >= max1)
+ then Lib_engine.NormalMetaVal(Ast_c.MetaPosVal(min2,max2))
+ else failwith "incompatible positions give to merge"
+ | (Lib_engine.NormalMetaVal(Ast_c.MetaTypeVal a),
+ Lib_engine.NormalMetaVal(Ast_c.MetaTypeVal b)) ->
+ Lib_engine.NormalMetaVal (Ast_c.MetaTypeVal (C_vs_c.merge_type a b))
+
+ | _ -> v
+ let print_mvar (_,s) = Format.print_string s
+ let print_value x = Pretty_print_engine.pp_binding_kind2 x
+ end
+
+module CFG =
+ struct
+ type node = int
+ type cfg = (F.node, F.edge) Ograph_extended.ograph_mutable
+ let predecessors cfg n = List.map fst ((cfg#predecessors n)#tolist)
+ let successors cfg n = List.map fst ((cfg#successors n)#tolist)
+ let extract_is_loop cfg n =
+ Control_flow_c.extract_is_loop (cfg#nodes#find n)
+ let print_node i = Format.print_string (i_to_s i)
+ let size cfg = cfg#nodes#length
+ end
+
+
+module WRAPPED_ENGINE = Wrapper_ctl.CTL_ENGINE_BIS (ENV) (CFG) (PRED)
+
+let print_bench _ = WRAPPED_ENGINE.print_bench()
+
+type pred = Lib_engine.predicate * Ast_cocci.meta_name Ast_ctl.modif
+
+(*****************************************************************************)
+let metavars_binding2_to_binding binding2 =
+ binding2 +> Common.map_filter (fun (s, kind2) ->
+ match kind2 with
+ | Lib_engine.NormalMetaVal kind -> Some (s, kind)
+ (* I thought it was Impossible to have this when called from
+ satbis_to_trans_info but it does not seems so *)
+ | Lib_engine.ParenVal _ -> None
+ | Lib_engine.LabelVal _ -> None
+ | Lib_engine.BadVal -> None (* should not occur *)
+ | Lib_engine.GoodVal -> None (* should not occur *)
+ )
+
+let metavars_binding_to_binding2 binding =
+ binding +> List.map (fun (s, kind) -> s, Lib_engine.NormalMetaVal kind)
+
+
+let (satbis_to_trans_info:
+ (nodei * Lib_engine.metavars_binding2 * Lib_engine.predicate) list ->
+ (nodei * Lib_engine.metavars_binding * Ast_cocci.rule_elem) list) =
+ fun xs ->
+ xs +> List.fold_left (fun prev (nodei, binding2, pred) ->
+ match pred with
+ | Lib_engine.Match (rule_elem) ->
+ if !Flag.track_iso_usage then show_isos rule_elem;
+ (nodei, metavars_binding2_to_binding binding2, rule_elem)
+ ::prev
+ (* see BindGood in asttotctl2 *)
+ | Lib_engine.BindGood (_) -> prev
+ | _ -> raise Impossible
+ ) []
+
+(*****************************************************************************)
+
+let rec coalesce_positions = function
+ [] -> []
+ | (x,Ast_c.MetaPosValList l)::rest ->
+ let (same,others) = List.partition (function (x1,_) -> x = x1) rest in
+ let ls =
+ List.concat
+ (List.map
+ (function
+ (_,Ast_c.MetaPosValList l) -> l
+ | _ -> failwith "unexpected non-position")
+ same) in
+ let new_ls = List.sort compare (l@ls) in
+ (x,Ast_c.MetaPosValList new_ls) :: coalesce_positions others
+ | x::rest -> x :: coalesce_positions rest
+
+(*****************************************************************************)
+(* Call ctl engine *)
+(*****************************************************************************)
+let (mysat2:
+ Lib_engine.model ->
+ (Lib_engine.ctlcocci * (pred list list)) ->
+ (Lib_engine.mvar list*Lib_engine.metavars_binding) ->
+ (Lib_engine.transformation_info * bool * Lib_engine.metavars_binding list)) =
+ fun (flow, label, states) ctl (used_after, binding) ->
+ let binding2 = metavars_binding_to_binding2 binding in
+ let (triples,(trans_info2, returned_any_states, used_after_envs)) =
+ WRAPPED_ENGINE.satbis (flow, label, states) ctl (used_after, binding2)
+ in
+ if not (!Flag_parsing_cocci.sgrep_mode || !Flag.sgrep_mode2 ||
+ !Flag_engine.allow_inconsistent_paths)
+ then Check_reachability.check_reachability triples flow;
+ let (trans_info2,used_after_fresh_envs) =
+ Postprocess_transinfo.process used_after binding2 trans_info2 in
+ let used_after_envs =
+ Common.uniq(List.map2 (@) used_after_fresh_envs used_after_envs) in
+ let trans_info = satbis_to_trans_info trans_info2 in
+ let newbindings = List.map metavars_binding2_to_binding used_after_envs in
+ let newbindings = List.map coalesce_positions newbindings in
+ (trans_info, returned_any_states, newbindings)
+
+let mysat a b c =
+ Common.profile_code "mysat" (fun () -> mysat2 a b c)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Common
+
+(*****************************************************************************)
+(* The functor argument *)
+(*****************************************************************************)
+
+(* info passed recursively in monad in addition to binding *)
+type xinfo = {
+ optional_storage_iso : bool;
+ optional_qualifier_iso : bool;
+ value_format_iso : bool;
+}
+
+module XMATCH = struct
+
+ (* ------------------------------------------------------------------------*)
+ (* Combinators history *)
+ (* ------------------------------------------------------------------------*)
+ (*
+ * version0:
+ * type ('a, 'b) matcher = 'a -> 'b -> bool
+ *
+ * version1: same but with a global variable holding the current binding
+ * BUT bug
+ * - can have multiple possibilities
+ * - globals sux
+ * - sometimes have to undo, cos if start match, then it binds,
+ * and if later it does not match, then must undo the first binds.
+ * ex: when match parameters, can try to match, but then we found far
+ * later that the last argument of a function does not match
+ * => have to uando the binding !!!
+ * (can handle that too with a global, by saving the
+ * global, ... but sux)
+ * => better not use global
+ *
+ * version2:
+ * type ('a, 'b) matcher = binding -> 'a -> 'b -> binding list
+ *
+ * Empty list mean failure (let matchfailure = []).
+ * To be able to have pretty code, have to use partial application
+ * powa, and so the type is in fact
+ *
+ * version3:
+ * type ('a, 'b) matcher = 'a -> 'b -> binding -> binding list
+ *
+ * Then by defining the correct combinators, can have quite pretty code (that
+ * looks like the clean code of version0).
+ *
+ * opti: return a lazy list of possible matchs ?
+ *
+ * version4: type tin = Lib_engine.metavars_binding
+ *)
+
+ (* ------------------------------------------------------------------------*)
+ (* Standard type and operators *)
+ (* ------------------------------------------------------------------------*)
+
+ type tin = {
+ extra: xinfo;
+ binding: Lib_engine.metavars_binding;
+ }
+ (* 'x is a ('a * 'b) but in fact dont care about 'b, we just tag the SP *)
+ (* opti? use set instead of list *)
+ type 'x tout = ('x * Lib_engine.metavars_binding) list
+
+ type ('a, 'b) matcher = 'a -> 'b -> tin -> ('a * 'b) tout
+
+ (* was >&&> *)
+ let (>>=) m1 m2 = fun tin ->
+ let xs = m1 tin in
+ let xxs = xs +> List.map (fun ((a,b), binding) ->
+ m2 a b {extra = tin.extra; binding = binding}
+ ) in
+ List.flatten xxs
+
+ (* Je compare les bindings retournés par les differentes branches.
+ * Si la deuxieme branche amene a des bindings qui sont deja presents
+ * dans la premiere branche, alors je ne les accepte pas.
+ *
+ * update: still useful now that julia better handle Exp directly via
+ * ctl tricks using positions ?
+ *)
+ let (>|+|>) m1 m2 = fun tin ->
+(* CHOICE
+ let xs = m1 tin in
+ if null xs
+ then m2 tin
+ else xs
+*)
+ let res1 = m1 tin in
+ let res2 = m2 tin in
+ let list_bindings_already = List.map snd res1 in
+ res1 ++
+ (res2 +> List.filter (fun (x, binding) ->
+ not
+ (list_bindings_already +> List.exists (fun already ->
+ Lib_engine.equal_binding binding already))
+ ))
+
+
+
+
+ let (>||>) m1 m2 = fun tin ->
+(* CHOICE
+ let xs = m1 tin in
+ if null xs
+ then m2 tin
+ else xs
+*)
+ (* opti? use set instead of list *)
+ m1 tin ++ m2 tin
+
+
+ let return res = fun tin ->
+ [res, tin.binding]
+
+ let fail = fun tin ->
+ []
+
+ let (>&&>) f m = fun tin ->
+ if f tin
+ then m tin
+ else fail tin
+
+
+ let mode = Cocci_vs_c_3.PatternMode
+
+ (* ------------------------------------------------------------------------*)
+ (* Exp *)
+ (* ------------------------------------------------------------------------*)
+ let cocciExp = fun expf expa node -> fun tin ->
+
+ let globals = ref [] in
+ let bigf = {
+ (* julia's style *)
+ Visitor_c.default_visitor_c with
+ Visitor_c.kexpr = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | [] -> (* failed *) k expb
+ | xs ->
+ globals := xs @ !globals;
+ if not !Flag_engine.disallow_nested_exps then k expb (* CHOICE *)
+ );
+ (* pad's style.
+ * push2 expr globals; k expr
+ * ...
+ * !globals +> List.fold_left (fun acc e -> acc >||> match_e_e expr e)
+ * (return false)
+ *
+ *)
+ }
+ in
+ Visitor_c.vk_node bigf node;
+ !globals +> List.map (fun ((a, _exp), binding) ->
+ (a, node), binding
+ )
+
+ (* same as cocciExp, but for expressions in an expression, not expressions
+ in a node *)
+ let cocciExpExp = fun expf expa expb -> fun tin ->
+
+ let globals = ref [] in
+ let bigf = {
+ (* julia's style *)
+ Visitor_c.default_visitor_c with
+ Visitor_c.kexpr = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | [] -> (* failed *) k expb
+ | xs ->
+ globals := xs @ !globals;
+ if not !Flag_engine.disallow_nested_exps then k expb (* CHOICE *)
+ );
+ (* pad's style.
+ * push2 expr globals; k expr
+ * ...
+ * !globals +> List.fold_left (fun acc e -> acc >||> match_e_e expr e)
+ * (return false)
+ *
+ *)
+ }
+ in
+ Visitor_c.vk_expr bigf expb;
+ !globals +> List.map (fun ((a, _exp), binding) ->
+ (a, expb), binding
+ )
+
+ let cocciTy = fun expf expa node -> fun tin ->
+
+ let globals = ref [] in
+ let bigf = {
+ Visitor_c.default_visitor_c with
+ Visitor_c.ktype = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | [] -> (* failed *) k expb
+ | xs -> globals := xs @ !globals);
+
+ }
+ in
+ Visitor_c.vk_node bigf node;
+ !globals +> List.map (fun ((a, _exp), binding) ->
+ (a, node), binding
+ )
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Distribute mcode *)
+ (* ------------------------------------------------------------------------*)
+ let tag_mck_pos mck posmck =
+ match mck with
+ | Ast_cocci.PLUS -> Ast_cocci.PLUS
+ | Ast_cocci.CONTEXT (pos, xs) ->
+ assert (pos = Ast_cocci.NoPos || pos = Ast_cocci.DontCarePos);
+ Ast_cocci.CONTEXT (posmck, xs)
+ | Ast_cocci.MINUS (pos, xs) ->
+ assert (pos = Ast_cocci.NoPos || pos = Ast_cocci.DontCarePos);
+ Ast_cocci.MINUS (posmck, xs)
+
+
+ let tag_mck_pos_mcode (x,info,mck,pos) posmck stuff = fun tin ->
+ [((x, info, tag_mck_pos mck posmck, pos),stuff), tin.binding]
+
+
+ let distrf (ii_of_x_f) =
+ fun mcode x -> fun tin ->
+ let (max, min) = Lib_parsing_c.max_min_by_pos (ii_of_x_f x)
+ in
+ let posmck = Ast_cocci.FixPos (min, max) (* subtil: and not max, min !!*)
+ in
+ tag_mck_pos_mcode mcode posmck x tin
+
+ let distrf_e = distrf (Lib_parsing_c.ii_of_expr)
+ let distrf_args = distrf (Lib_parsing_c.ii_of_args)
+ let distrf_type = distrf (Lib_parsing_c.ii_of_type)
+ let distrf_param = distrf (Lib_parsing_c.ii_of_param)
+ let distrf_params = distrf (Lib_parsing_c.ii_of_params)
+ let distrf_ini = distrf (Lib_parsing_c.ii_of_ini)
+ let distrf_node = distrf (Lib_parsing_c.ii_of_node)
+ let distrf_struct_fields = distrf (Lib_parsing_c.ii_of_struct_fields)
+ let distrf_cst = distrf (Lib_parsing_c.ii_of_cst)
+ let distrf_define_params = distrf (Lib_parsing_c.ii_of_define_params)
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Constraints on metavariable values *)
+ (* ------------------------------------------------------------------------*)
+ let check_constraints matcher constraints exp = fun f tin ->
+ let rec loop = function
+ [] -> f () tin (* success *)
+ | c::cs ->
+ match matcher c exp tin with
+ [] (* failure *) -> loop cs
+ | _ (* success *) -> fail tin in
+ loop constraints
+
+ let check_pos_constraints constraints pvalu f tin =
+ check_constraints
+ (fun c exp tin ->
+ let success = [[]] in
+ let failure = [] in
+ (match Common.optionise (fun () -> tin.binding +> List.assoc c) with
+ Some valu' ->
+ if Cocci_vs_c_3.equal_metavarval exp valu'
+ then success else failure
+ | None ->
+ (* if the variable is not there, it puts no constraints *)
+ (* not sure this is still useful *)
+ failure))
+ constraints pvalu f tin
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment *)
+ (* ------------------------------------------------------------------------*)
+ (* pre: if have declared a new metavar that hide another one, then
+ * must be passed with a binding that deleted this metavar
+ *
+ * Here we dont use the keep argument of julia. cf f(X,X), J'ai
+ * besoin de garder le X en interne, meme si julia s'en fout elle du
+ * X et qu'elle a mis X a DontSaved.
+ *)
+ let check_add_metavars_binding strip _keep inherited = fun (k, valu) tin ->
+ (match Common.optionise (fun () -> tin.binding +> List.assoc k) with
+ | Some (valu') ->
+ if Cocci_vs_c_3.equal_metavarval valu valu'
+ then Some tin.binding
+ else None
+
+ | None ->
+ if inherited
+ then None
+ else
+ let valu' =
+ match valu with
+ Ast_c.MetaIdVal a -> Ast_c.MetaIdVal a
+ | Ast_c.MetaFuncVal a -> Ast_c.MetaFuncVal a
+ | Ast_c.MetaLocalFuncVal a -> Ast_c.MetaLocalFuncVal a (*more?*)
+ | Ast_c.MetaExprVal a ->
+ Ast_c.MetaExprVal
+ (if strip
+ then Lib_parsing_c.al_expr a
+ else Lib_parsing_c.semi_al_expr a)
+ | Ast_c.MetaExprListVal a ->
+ Ast_c.MetaExprListVal
+ (if strip
+ then Lib_parsing_c.al_arguments a
+ else Lib_parsing_c.semi_al_arguments a)
+
+ | Ast_c.MetaStmtVal a ->
+ Ast_c.MetaStmtVal
+ (if strip
+ then Lib_parsing_c.al_statement a
+ else Lib_parsing_c.semi_al_statement a)
+ | Ast_c.MetaTypeVal a ->
+ Ast_c.MetaTypeVal
+ (if strip
+ then Lib_parsing_c.al_type a
+ else Lib_parsing_c.semi_al_type a)
+
+ | Ast_c.MetaListlenVal a -> Ast_c.MetaListlenVal a
+
+ | Ast_c.MetaParamVal a -> failwith "not handling MetaParamVal"
+ | Ast_c.MetaParamListVal a ->
+ Ast_c.MetaParamListVal
+ (if strip
+ then Lib_parsing_c.al_params a
+ else Lib_parsing_c.semi_al_params a)
+
+ | Ast_c.MetaPosVal (pos1,pos2) -> Ast_c.MetaPosVal (pos1,pos2)
+ | Ast_c.MetaPosValList l -> Ast_c.MetaPosValList l
+ in Some (tin.binding +> Common.insert_assoc (k, valu'))
+ )
+
+ let envf keep inherited = fun (k, valu, get_max_min) f tin ->
+ let x = Ast_cocci.unwrap_mcode k in
+ match check_add_metavars_binding true keep inherited (x, valu) tin with
+ | Some binding ->
+ let new_tin = {extra = tin.extra; binding = binding} in
+ (match Ast_cocci.get_pos_var k with
+ Ast_cocci.MetaPos(name,constraints,per,keep,inherited) ->
+ let pvalu =
+ let (file,min,max) = get_max_min() in
+ Ast_c.MetaPosValList[(file,min,max)] in
+ (* check constraints. success means that there is a match with
+ one of the constraints, which will ultimately result in
+ failure. *)
+ check_pos_constraints constraints pvalu
+ (function () ->
+ (* constraints are satisfied, now see if we are compatible
+ with existing bindings *)
+ function new_tin ->
+ let x = Ast_cocci.unwrap_mcode name in
+ (match
+ check_add_metavars_binding false keep inherited (x, pvalu)
+ new_tin with
+ | Some binding ->
+ f () {extra = new_tin.extra; binding = binding}
+ | None -> fail tin))
+ new_tin
+ | Ast_cocci.NoMetaPos -> f () new_tin)
+ | None -> fail tin
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment, allbounds *)
+ (* ------------------------------------------------------------------------*)
+ (* all referenced inherited variables have to be bound. This would
+ * be naturally checked for the minus or context ones in the
+ * matching process, but have to check the plus ones as well. The
+ * result of get_inherited contains all of these, but the potential
+ * redundant checking for the minus and context ones is probably not
+ * a big deal. If it's a problem, could fix free_vars to distinguish
+ * between + variables and the other ones. *)
+
+ let (all_bound : Ast_cocci.meta_name list -> tin -> bool) = fun l tin ->
+ l +> List.for_all (fun inhvar ->
+ match Common.optionise (fun () -> tin.binding +> List.assoc inhvar) with
+ | Some _ -> true
+ | None -> false
+ )
+
+ let optional_storage_flag f = fun tin ->
+ f (tin.extra.optional_storage_iso) tin
+
+ let optional_qualifier_flag f = fun tin ->
+ f (tin.extra.optional_qualifier_iso) tin
+
+ let value_format_flag f = fun tin ->
+ f (tin.extra.value_format_iso) tin
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Tokens *)
+ (* ------------------------------------------------------------------------*)
+ let tokenf ia ib = fun tin ->
+ let pos = Ast_c.info_to_fixpos ib in
+ let posmck = Ast_cocci.FixPos (pos, pos) in
+ let finish tin = tag_mck_pos_mcode ia posmck ib tin in
+ match Ast_cocci.get_pos_var ia with
+ Ast_cocci.MetaPos(name,constraints,per,keep,inherited) ->
+ let mpos = Lib_parsing_c.lin_col_by_pos [ib] in
+ let pvalu = Ast_c.MetaPosValList [mpos] in
+ check_pos_constraints constraints pvalu
+ (function () ->
+ (* constraints are satisfied, now see if we are compatible
+ with existing bindings *)
+ function new_tin ->
+ let x = Ast_cocci.unwrap_mcode name in
+ (match
+ check_add_metavars_binding false keep inherited (x, pvalu) tin
+ with
+ Some binding -> finish {extra = tin.extra; binding = binding}
+ | None -> fail tin))
+ tin
+ | _ -> finish tin
+
+ let tokenf_mck mck ib = fun tin ->
+ let pos = Ast_c.info_to_fixpos ib in
+ let posmck = Ast_cocci.FixPos (pos, pos) in
+ [(tag_mck_pos mck posmck, ib), tin.binding]
+
+end
+
+(*****************************************************************************)
+(* Entry point *)
+(*****************************************************************************)
+module MATCH = Cocci_vs_c_3.COCCI_VS_C (XMATCH)
+
+
+let match_re_node2 dropped_isos a b binding =
+
+ let tin = {
+ XMATCH.extra = {
+ optional_storage_iso = not(List.mem "optional_storage" dropped_isos);
+ optional_qualifier_iso = not(List.mem "optional_qualifier" dropped_isos);
+ value_format_iso = not(List.mem "value_format" dropped_isos);
+ };
+ XMATCH.binding = binding;
+ } in
+
+ MATCH.rule_elem_node a b tin
+ (* take only the tagged-SP, the 'a' *)
+ +> List.map (fun ((a,_b), binding) -> a, binding)
+
+
+let match_re_node a b c d =
+ Common.profile_code "Pattern3.match_re_node"
+ (fun () -> match_re_node2 a b c d)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Common
+
+(*****************************************************************************)
+(* The functor argument *)
+(*****************************************************************************)
+
+(* info passed recursively in monad in addition to binding *)
+type xinfo = {
+ optional_storage_iso : bool;
+ optional_qualifier_iso : bool;
+ value_format_iso : bool;
+}
+
+module XMATCH = struct
+
+ (* ------------------------------------------------------------------------*)
+ (* Combinators history *)
+ (* ------------------------------------------------------------------------*)
+ (*
+ * version0:
+ * type ('a, 'b) matcher = 'a -> 'b -> bool
+ *
+ * version1: same but with a global variable holding the current binding
+ * BUT bug
+ * - can have multiple possibilities
+ * - globals sux
+ * - sometimes have to undo, cos if start match, then it binds,
+ * and if later it does not match, then must undo the first binds.
+ * ex: when match parameters, can try to match, but then we found far
+ * later that the last argument of a function does not match
+ * => have to uando the binding !!!
+ * (can handle that too with a global, by saving the
+ * global, ... but sux)
+ * => better not use global
+ *
+ * version2:
+ * type ('a, 'b) matcher = binding -> 'a -> 'b -> binding list
+ *
+ * Empty list mean failure (let matchfailure = []).
+ * To be able to have pretty code, have to use partial application
+ * powa, and so the type is in fact
+ *
+ * version3:
+ * type ('a, 'b) matcher = 'a -> 'b -> binding -> binding list
+ *
+ * Then by defining the correct combinators, can have quite pretty code (that
+ * looks like the clean code of version0).
+ *
+ * opti: return a lazy list of possible matchs ?
+ *
+ * version4: type tin = Lib_engine.metavars_binding
+ *)
+
+ (* ------------------------------------------------------------------------*)
+ (* Standard type and operators *)
+ (* ------------------------------------------------------------------------*)
+
+ type tin = {
+ extra: xinfo;
+ binding: Lib_engine.metavars_binding;
+ binding0: Lib_engine.metavars_binding; (* inherited bindings *)
+ }
+ (* 'x is a ('a * 'b) but in fact dont care about 'b, we just tag the SP *)
+ (* opti? use set instead of list *)
+ type 'x tout = ('x * Lib_engine.metavars_binding) list
+
+ type ('a, 'b) matcher = 'a -> 'b -> tin -> ('a * 'b) tout
+
+ (* was >&&> *)
+ let (>>=) m1 m2 = fun tin ->
+ let xs = m1 tin in
+ let xxs = xs +> List.map (fun ((a,b), binding) ->
+ m2 a b {tin with binding = binding}
+ ) in
+ List.flatten xxs
+
+ (* Je compare les bindings retournés par les differentes branches.
+ * Si la deuxieme branche amene a des bindings qui sont deja presents
+ * dans la premiere branche, alors je ne les accepte pas.
+ *
+ * update: still useful now that julia better handle Exp directly via
+ * ctl tricks using positions ?
+ *)
+ let (>|+|>) m1 m2 = fun tin ->
+(* CHOICE
+ let xs = m1 tin in
+ if null xs
+ then m2 tin
+ else xs
+*)
+ let res1 = m1 tin in
+ let res2 = m2 tin in
+ let list_bindings_already = List.map snd res1 in
+ res1 ++
+ (res2 +> List.filter (fun (x, binding) ->
+ not
+ (list_bindings_already +> List.exists (fun already ->
+ Lib_engine.equal_binding binding already))
+ ))
+
+
+
+
+ let (>||>) m1 m2 = fun tin ->
+(* CHOICE
+ let xs = m1 tin in
+ if null xs
+ then m2 tin
+ else xs
+*)
+ (* opti? use set instead of list *)
+ m1 tin ++ m2 tin
+
+
+ let return res = fun tin ->
+ [res, tin.binding]
+
+ let fail = fun tin ->
+ []
+
+ let (>&&>) f m = fun tin ->
+ if f tin
+ then m tin
+ else fail tin
+
+
+ let mode = Cocci_vs_c_3.PatternMode
+
+ (* ------------------------------------------------------------------------*)
+ (* Exp *)
+ (* ------------------------------------------------------------------------*)
+ let cocciExp = fun expf expa node -> fun tin ->
+
+ let globals = ref [] in
+ let bigf = {
+ (* julia's style *)
+ Visitor_c.default_visitor_c with
+ Visitor_c.kexpr = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | [] -> (* failed *) k expb
+ | xs ->
+ globals := xs @ !globals;
+ if not !Flag_engine.disallow_nested_exps then k expb (* CHOICE *)
+ );
+ (* pad's style.
+ * push2 expr globals; k expr
+ * ...
+ * !globals +> List.fold_left (fun acc e -> acc >||> match_e_e expr e)
+ * (return false)
+ *
+ *)
+ }
+ in
+ Visitor_c.vk_node bigf node;
+ !globals +> List.map (fun ((a, _exp), binding) ->
+ (a, node), binding
+ )
+
+ (* same as cocciExp, but for expressions in an expression, not expressions
+ in a node *)
+ let cocciExpExp = fun expf expa expb -> fun tin ->
+
+ let globals = ref [] in
+ let bigf = {
+ (* julia's style *)
+ Visitor_c.default_visitor_c with
+ Visitor_c.kexpr = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | [] -> (* failed *) k expb
+ | xs ->
+ globals := xs @ !globals;
+ if not !Flag_engine.disallow_nested_exps then k expb (* CHOICE *)
+ );
+ (* pad's style.
+ * push2 expr globals; k expr
+ * ...
+ * !globals +> List.fold_left (fun acc e -> acc >||> match_e_e expr e)
+ * (return false)
+ *
+ *)
+ }
+ in
+ Visitor_c.vk_expr bigf expb;
+ !globals +> List.map (fun ((a, _exp), binding) ->
+ (a, expb), binding
+ )
+
+ let cocciTy = fun expf expa node -> fun tin ->
+
+ let globals = ref [] in
+ let bigf = {
+ Visitor_c.default_visitor_c with
+ Visitor_c.ktype = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | [] -> (* failed *) k expb
+ | xs -> globals := xs @ !globals);
+
+ }
+ in
+ Visitor_c.vk_node bigf node;
+ !globals +> List.map (fun ((a, _exp), binding) ->
+ (a, node), binding
+ )
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Distribute mcode *)
+ (* ------------------------------------------------------------------------*)
+ let tag_mck_pos mck posmck =
+ match mck with
+ | Ast_cocci.PLUS -> Ast_cocci.PLUS
+ | Ast_cocci.CONTEXT (pos, xs) ->
+ assert (pos = Ast_cocci.NoPos || pos = Ast_cocci.DontCarePos);
+ Ast_cocci.CONTEXT (posmck, xs)
+ | Ast_cocci.MINUS (pos, xs) ->
+ assert (pos = Ast_cocci.NoPos || pos = Ast_cocci.DontCarePos);
+ Ast_cocci.MINUS (posmck, xs)
+
+
+ let tag_mck_pos_mcode (x,info,mck,pos) posmck stuff = fun tin ->
+ [((x, info, tag_mck_pos mck posmck, pos),stuff), tin.binding]
+
+
+ let distrf (ii_of_x_f) =
+ fun mcode x -> fun tin ->
+ let (max, min) = Lib_parsing_c.max_min_by_pos (ii_of_x_f x)
+ in
+ let posmck = Ast_cocci.FixPos (min, max) (* subtil: and not max, min !!*)
+ in
+ tag_mck_pos_mcode mcode posmck x tin
+
+ let distrf_e = distrf (Lib_parsing_c.ii_of_expr)
+ let distrf_args = distrf (Lib_parsing_c.ii_of_args)
+ let distrf_type = distrf (Lib_parsing_c.ii_of_type)
+ let distrf_param = distrf (Lib_parsing_c.ii_of_param)
+ let distrf_params = distrf (Lib_parsing_c.ii_of_params)
+ let distrf_ini = distrf (Lib_parsing_c.ii_of_ini)
+ let distrf_node = distrf (Lib_parsing_c.ii_of_node)
+ let distrf_struct_fields = distrf (Lib_parsing_c.ii_of_struct_fields)
+ let distrf_cst = distrf (Lib_parsing_c.ii_of_cst)
+ let distrf_define_params = distrf (Lib_parsing_c.ii_of_define_params)
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Constraints on metavariable values *)
+ (* ------------------------------------------------------------------------*)
+ let check_constraints matcher constraints exp = fun f tin ->
+ let rec loop = function
+ [] -> f () tin (* success *)
+ | c::cs ->
+ match matcher c exp tin with
+ [] (* failure *) -> loop cs
+ | _ (* success *) -> fail tin in
+ loop constraints
+
+ let check_pos_constraints constraints pvalu f tin =
+ check_constraints
+ (fun c exp tin ->
+ let success = [[]] in
+ let failure = [] in
+ (* relies on the fact that constraints on pos variables must refer to
+ inherited variables *)
+ (match Common.optionise (fun () -> tin.binding0 +> List.assoc c) with
+ Some valu' ->
+ if Cocci_vs_c_3.equal_metavarval exp valu'
+ then success else failure
+ | None ->
+ (* if the variable is not there, it puts no constraints *)
+ (* not sure this is still useful *)
+ failure))
+ constraints pvalu f tin
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment *)
+ (* ------------------------------------------------------------------------*)
+ (* pre: if have declared a new metavar that hide another one, then
+ * must be passed with a binding that deleted this metavar
+ *
+ * Here we dont use the keep argument of julia. cf f(X,X), J'ai
+ * besoin de garder le X en interne, meme si julia s'en fout elle du
+ * X et qu'elle a mis X a DontSaved.
+ *)
+ let check_add_metavars_binding strip _keep inherited = fun (k, valu) tin ->
+ if inherited
+ then
+ match Common.optionise (fun () -> tin.binding0 +> List.assoc k) with
+ | Some (valu') ->
+ if Cocci_vs_c_3.equal_metavarval valu valu'
+ then Some tin.binding
+ else None
+ | None -> None
+ else
+ match Common.optionise (fun () -> tin.binding +> List.assoc k) with
+ | Some (valu') ->
+ if Cocci_vs_c_3.equal_metavarval valu valu'
+ then Some tin.binding
+ else None
+
+ | None ->
+ let valu' =
+ match valu with
+ Ast_c.MetaIdVal a -> Ast_c.MetaIdVal a
+ | Ast_c.MetaFuncVal a -> Ast_c.MetaFuncVal a
+ | Ast_c.MetaLocalFuncVal a -> Ast_c.MetaLocalFuncVal a (*more?*)
+ | Ast_c.MetaExprVal a ->
+ Ast_c.MetaExprVal
+ (if strip
+ then Lib_parsing_c.al_expr a
+ else Lib_parsing_c.semi_al_expr a)
+ | Ast_c.MetaExprListVal a ->
+ Ast_c.MetaExprListVal
+ (if strip
+ then Lib_parsing_c.al_arguments a
+ else Lib_parsing_c.semi_al_arguments a)
+
+ | Ast_c.MetaStmtVal a ->
+ Ast_c.MetaStmtVal
+ (if strip
+ then Lib_parsing_c.al_statement a
+ else Lib_parsing_c.semi_al_statement a)
+ | Ast_c.MetaTypeVal a ->
+ Ast_c.MetaTypeVal
+ (if strip
+ then Lib_parsing_c.al_type a
+ else Lib_parsing_c.semi_al_type a)
+
+ | Ast_c.MetaListlenVal a -> Ast_c.MetaListlenVal a
+
+ | Ast_c.MetaParamVal a -> failwith "not handling MetaParamVal"
+ | Ast_c.MetaParamListVal a ->
+ Ast_c.MetaParamListVal
+ (if strip
+ then Lib_parsing_c.al_params a
+ else Lib_parsing_c.semi_al_params a)
+
+ | Ast_c.MetaPosVal (pos1,pos2) -> Ast_c.MetaPosVal (pos1,pos2)
+ | Ast_c.MetaPosValList l -> Ast_c.MetaPosValList l
+ in Some (tin.binding +> Common.insert_assoc (k, valu'))
+
+ let envf keep inherited = fun (k, valu, get_max_min) f tin ->
+ let x = Ast_cocci.unwrap_mcode k in
+ match check_add_metavars_binding true keep inherited (x, valu) tin with
+ | Some binding ->
+ let new_tin = {tin with binding = binding} in
+ (match Ast_cocci.get_pos_var k with
+ Ast_cocci.MetaPos(name,constraints,per,keep,inherited) ->
+ let pvalu =
+ let (file,min,max) = get_max_min() in
+ Ast_c.MetaPosValList[(file,min,max)] in
+ (* check constraints. success means that there is a match with
+ one of the constraints, which will ultimately result in
+ failure. *)
+ check_pos_constraints constraints pvalu
+ (function () ->
+ (* constraints are satisfied, now see if we are compatible
+ with existing bindings *)
+ function new_tin ->
+ let x = Ast_cocci.unwrap_mcode name in
+ (match
+ check_add_metavars_binding false keep inherited (x, pvalu)
+ new_tin with
+ | Some binding ->
+ f () {new_tin with binding = binding}
+ | None -> fail tin))
+ new_tin
+ | Ast_cocci.NoMetaPos -> f () new_tin)
+ | None -> fail tin
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment, allbounds *)
+ (* ------------------------------------------------------------------------*)
+ (* all referenced inherited variables have to be bound. This would
+ * be naturally checked for the minus or context ones in the
+ * matching process, but have to check the plus ones as well. The
+ * result of get_inherited contains all of these, but the potential
+ * redundant checking for the minus and context ones is probably not
+ * a big deal. If it's a problem, could fix free_vars to distinguish
+ * between + variables and the other ones. *)
+
+ let (all_bound : Ast_cocci.meta_name list -> tin -> bool) = fun l tin ->
+ l +> List.for_all (fun inhvar ->
+ match Common.optionise (fun () -> tin.binding0 +> List.assoc inhvar) with
+ | Some _ -> true
+ | None -> false
+ )
+
+ let optional_storage_flag f = fun tin ->
+ f (tin.extra.optional_storage_iso) tin
+
+ let optional_qualifier_flag f = fun tin ->
+ f (tin.extra.optional_qualifier_iso) tin
+
+ let value_format_flag f = fun tin ->
+ f (tin.extra.value_format_iso) tin
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Tokens *)
+ (* ------------------------------------------------------------------------*)
+ let tokenf ia ib = fun tin ->
+ let pos = Ast_c.info_to_fixpos ib in
+ let posmck = Ast_cocci.FixPos (pos, pos) in
+ let finish tin = tag_mck_pos_mcode ia posmck ib tin in
+ match Ast_cocci.get_pos_var ia with
+ Ast_cocci.MetaPos(name,constraints,per,keep,inherited) ->
+ let mpos = Lib_parsing_c.lin_col_by_pos [ib] in
+ let pvalu = Ast_c.MetaPosValList [mpos] in
+ check_pos_constraints constraints pvalu
+ (function () ->
+ (* constraints are satisfied, now see if we are compatible
+ with existing bindings *)
+ function new_tin ->
+ let x = Ast_cocci.unwrap_mcode name in
+ (match
+ check_add_metavars_binding false keep inherited (x, pvalu) tin
+ with
+ Some binding -> finish {tin with binding = binding}
+ | None -> fail tin))
+ tin
+ | _ -> finish tin
+
+ let tokenf_mck mck ib = fun tin ->
+ let pos = Ast_c.info_to_fixpos ib in
+ let posmck = Ast_cocci.FixPos (pos, pos) in
+ [(tag_mck_pos mck posmck, ib), tin.binding]
+
+end
+
+(*****************************************************************************)
+(* Entry point *)
+(*****************************************************************************)
+module MATCH = Cocci_vs_c_3.COCCI_VS_C (XMATCH)
+
+
+let match_re_node2 dropped_isos a b binding0 =
+
+ let tin = {
+ XMATCH.extra = {
+ optional_storage_iso = not(List.mem "optional_storage" dropped_isos);
+ optional_qualifier_iso = not(List.mem "optional_qualifier" dropped_isos);
+ value_format_iso = not(List.mem "value_format" dropped_isos);
+ };
+ XMATCH.binding = [];
+ XMATCH.binding0 = binding0;
+ } in
+
+ MATCH.rule_elem_node a b tin
+ (* take only the tagged-SP, the 'a' *)
+ +> List.map (fun ((a,_b), binding) -> a, binding)
+
+
+let match_re_node a b c d =
+ Common.profile_code "Pattern3.match_re_node"
+ (fun () -> match_re_node2 a b c d)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Common
+
+module F = Control_flow_c
+
+(*****************************************************************************)
+(* The functor argument *)
+(*****************************************************************************)
+
+(* info passed recursively in monad in addition to binding *)
+type xinfo = {
+ optional_storage_iso : bool;
+ optional_qualifier_iso : bool;
+ value_format_iso : bool;
+ current_rule_name : string; (* used for errors *)
+}
+
+module XTRANS = struct
+
+ (* ------------------------------------------------------------------------*)
+ (* Combinators history *)
+ (* ------------------------------------------------------------------------*)
+ (*
+ * version0:
+ * type ('a, 'b) transformer =
+ * 'a -> 'b -> Lib_engine.metavars_binding -> 'b
+ * exception NoMatch
+ *
+ * version1:
+ * type ('a, 'b) transformer =
+ * 'a -> 'b -> Lib_engine.metavars_binding -> 'b option
+ * use an exception monad
+ *
+ * version2:
+ * type tin = Lib_engine.metavars_binding
+ *)
+
+ (* ------------------------------------------------------------------------*)
+ (* Standard type and operators *)
+ (* ------------------------------------------------------------------------*)
+
+ type tin = {
+ extra: xinfo;
+ binding: Lib_engine.metavars_binding;
+ }
+ type 'x tout = 'x option
+
+ type ('a, 'b) matcher = 'a -> 'b -> tin -> ('a * 'b) tout
+
+ let (>>=) m f = fun tin ->
+ match m tin with
+ | None -> None
+ | Some (a,b) -> f a b tin
+
+ let return = fun x -> fun tin ->
+ Some x
+
+ (* can have fail in transform now that the process is deterministic ? *)
+ let fail = fun tin ->
+ None
+
+ let (>||>) m1 m2 = fun tin ->
+ match m1 tin with
+ | None -> m2 tin
+ | Some x -> Some x (* stop as soon as have found something *)
+
+ let (>|+|>) m1 m2 = m1 >||> m2
+
+ let (>&&>) f m = fun tin ->
+ if f tin then m tin else fail tin
+
+ let optional_storage_flag f = fun tin ->
+ f (tin.extra.optional_storage_iso) tin
+
+ let optional_qualifier_flag f = fun tin ->
+ f (tin.extra.optional_qualifier_iso) tin
+
+ let value_format_flag f = fun tin ->
+ f (tin.extra.value_format_iso) tin
+
+ let mode = Cocci_vs_c_3.TransformMode
+
+ (* ------------------------------------------------------------------------*)
+ (* Exp *)
+ (* ------------------------------------------------------------------------*)
+ let cocciExp = fun expf expa node -> fun tin ->
+
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.kexpr_s = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | None -> (* failed *) k expb
+ | Some (x, expb) -> expb);
+ }
+ in
+ Some (expa, Visitor_c.vk_node_s bigf node)
+
+
+ (* same as cocciExp, but for expressions in an expression, not expressions
+ in a node *)
+ let cocciExpExp = fun expf expa expb -> fun tin ->
+
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.kexpr_s = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | None -> (* failed *) k expb
+ | Some (x, expb) -> expb);
+ }
+ in
+ Some (expa, Visitor_c.vk_expr_s bigf expb)
+
+
+ let cocciTy = fun expf expa node -> fun tin ->
+
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.ktype_s = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | None -> (* failed *) k expb
+ | Some (x, expb) -> expb);
+ }
+ in
+ Some (expa, Visitor_c.vk_node_s bigf node)
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Tokens *)
+ (* ------------------------------------------------------------------------*)
+ let check_pos info mck pos =
+ match mck with
+ | Ast_cocci.PLUS -> raise Impossible
+ | Ast_cocci.CONTEXT (Ast_cocci.FixPos (i1,i2),_)
+ | Ast_cocci.MINUS (Ast_cocci.FixPos (i1,i2),_) ->
+ pos <= i2 && pos >= i1
+ | Ast_cocci.CONTEXT (Ast_cocci.DontCarePos,_)
+ | Ast_cocci.MINUS (Ast_cocci.DontCarePos,_) ->
+ true
+ | _ ->
+ match info with
+ Some info ->
+ failwith
+ (Printf.sprintf
+ "wierd: dont have position info for the mcodekind in line %d column %d"
+ info.Ast_cocci.line info.Ast_cocci.column)
+ | None ->
+ failwith "wierd: dont have position info for the mcodekind"
+
+
+ let tag_with_mck mck ib = fun tin ->
+
+ let cocciinforef = ib.Ast_c.cocci_tag in
+ let (oldmcode, oldenv) = !cocciinforef in
+
+ let mck =
+ if !Flag_parsing_cocci.sgrep_mode
+ then Sgrep.process_sgrep ib mck
+ else mck
+ in
+ (match mck, Ast_c.pinfo_of_info ib with
+ | _, Ast_c.AbstractLineTok _ -> raise Impossible
+ | Ast_cocci.MINUS(_), Ast_c.ExpandedTok _ ->
+ failwith ("try to delete an expanded token: " ^ (Ast_c.str_of_info ib))
+ | _ -> ()
+ );
+
+ match (oldmcode,mck) with
+ | (Ast_cocci.CONTEXT(_,Ast_cocci.NOTHING), _)
+ | (_, Ast_cocci.CONTEXT(_,Ast_cocci.NOTHING))
+ ->
+ cocciinforef := (mck, tin.binding);
+ ib
+
+ | _ ->
+ if (oldmcode, oldenv) = (mck, tin.binding)
+ then begin
+ if !Flag.show_misc
+ then pr2 "already tagged but with same mcode, so safe";
+ ib
+ end
+ else
+ if !Flag.sgrep_mode2
+ then ib (* safe *)
+ else
+ begin
+ Format.set_formatter_out_channel stderr;
+ Common.pr2 "SP mcode ";
+ Pretty_print_cocci.print_mcodekind oldmcode;
+ Format.print_newline();
+ Common.pr2 "C code mcode ";
+ Pretty_print_cocci.print_mcodekind mck;
+ Format.print_newline();
+ Format.print_flush();
+ failwith
+ (Common.sprintf "%s: already tagged token:\n%s"
+ tin.extra.current_rule_name
+ (Common.error_message (Ast_c.file_of_info ib)
+ (Ast_c.str_of_info ib, Ast_c.opos_of_info ib)))
+ end
+
+ let tokenf ia ib = fun tin ->
+ let (_,i,mck,_) = ia in
+ let pos = Ast_c.info_to_fixpos ib in
+ if check_pos (Some i) mck pos
+ then return (ia, tag_with_mck mck ib tin) tin
+ else fail tin
+
+ let tokenf_mck mck ib = fun tin ->
+ let pos = Ast_c.info_to_fixpos ib in
+ if check_pos None mck pos
+ then return (mck, tag_with_mck mck ib tin) tin
+ else fail tin
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Distribute mcode *)
+ (* ------------------------------------------------------------------------*)
+
+ (* When in the SP we attach something to a metavariable, or delete it, as in
+ * - S
+ * + foo();
+ * we have to minusize all the token that compose S in the C code, and
+ * attach the 'foo();' to the right token, the one at the very right.
+ *)
+
+ type 'a distributer =
+ (Ast_c.info -> Ast_c.info) * (* what to do on left *)
+ (Ast_c.info -> Ast_c.info) * (* what to do on middle *)
+ (Ast_c.info -> Ast_c.info) * (* what to do on right *)
+ (Ast_c.info -> Ast_c.info) -> (* what to do on both *)
+ 'a -> 'a
+
+ let distribute_mck mcodekind distributef expr tin =
+ match mcodekind with
+ | Ast_cocci.MINUS (pos,any_xxs) ->
+ distributef (
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,any_xxs)) ib tin),
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,[])) ib tin),
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,[])) ib tin),
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,any_xxs)) ib tin)
+ ) expr
+ | Ast_cocci.CONTEXT (pos,any_befaft) ->
+ (match any_befaft with
+ | Ast_cocci.NOTHING -> expr
+
+ | Ast_cocci.BEFORE xxs ->
+ distributef (
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFORE xxs)) ib tin),
+ (fun x -> x),
+ (fun x -> x),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFORE xxs)) ib tin)
+ ) expr
+ | Ast_cocci.AFTER xxs ->
+ distributef (
+ (fun x -> x),
+ (fun x -> x),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.AFTER xxs)) ib tin),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.AFTER xxs)) ib tin)
+ ) expr
+
+ | Ast_cocci.BEFOREAFTER (xxs, yys) ->
+ distributef (
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFORE xxs)) ib tin),
+ (fun x -> x),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.AFTER yys)) ib tin),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFOREAFTER (xxs,yys)))
+ ib tin)
+ ) expr
+
+ )
+ | Ast_cocci.PLUS -> raise Impossible
+
+
+ (* use new strategy, collect ii, sort, recollect and tag *)
+
+ let mk_bigf (maxpos, minpos) (lop,mop,rop,bop) =
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.kinfo_s = (fun (k,bigf) i ->
+ let pos = Ast_c.info_to_fixpos i in
+ match () with
+ | _ when Ast_cocci.equal_pos pos maxpos &&
+ Ast_cocci.equal_pos pos minpos -> bop i
+ | _ when Ast_cocci.equal_pos pos maxpos -> rop i
+ | _ when Ast_cocci.equal_pos pos minpos -> lop i
+ | _ -> mop i
+ )
+ } in
+ bigf
+
+ let distribute_mck_expr (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_expr_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_args (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_args_splitted_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_type (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_type_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_ini (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_ini_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_param (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_param_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_params (maxpos, minpos) = fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_params_splitted_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let distribute_mck_node (maxpos, minpos) = fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_node_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let distribute_mck_struct_fields (maxpos, minpos) =
+ fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_struct_fields_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let distribute_mck_cst (maxpos, minpos) =
+ fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_cst_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+
+ let distribute_mck_define_params (maxpos, minpos) = fun (lop,mop,rop,bop) ->
+ fun x ->
+ Visitor_c.vk_define_params_splitted_s
+ (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let get_pos mck =
+ match mck with
+ | Ast_cocci.PLUS -> raise Impossible
+ | Ast_cocci.CONTEXT (Ast_cocci.FixPos (i1,i2),_)
+ | Ast_cocci.MINUS (Ast_cocci.FixPos (i1,i2),_) ->
+ Ast_cocci.FixPos (i1,i2)
+ | Ast_cocci.CONTEXT (Ast_cocci.DontCarePos,_)
+ | Ast_cocci.MINUS (Ast_cocci.DontCarePos,_) ->
+ Ast_cocci.DontCarePos
+ | _ -> failwith "wierd: dont have position info for the mcodekind"
+
+ let distrf (ii_of_x_f, distribute_mck_x_f) =
+ fun ia x -> fun tin ->
+ let mck = Ast_cocci.get_mcodekind ia in
+ let (max, min) = Lib_parsing_c.max_min_by_pos (ii_of_x_f x)
+ in
+ if
+ (* bug: check_pos mck max && check_pos mck min
+ *
+ * if do that then if have - f(...); and in C f(1,2); then we
+ * would get a "already tagged" because the '...' would sucess in
+ * transformaing both '1' and '1,2'. So being in the range is not
+ * enough. We must be equal exactly to the range!
+ *)
+ (match get_pos mck with
+ | Ast_cocci.DontCarePos -> true
+ | Ast_cocci.FixPos (i1, i2) ->
+ i1 = min && i2 = max
+ | _ -> raise Impossible
+ )
+
+ then
+ return (
+ ia,
+ distribute_mck mck (distribute_mck_x_f (max,min)) x tin
+ ) tin
+ else fail tin
+
+
+ let distrf_e = distrf (Lib_parsing_c.ii_of_expr, distribute_mck_expr)
+ let distrf_args = distrf (Lib_parsing_c.ii_of_args, distribute_mck_args)
+ let distrf_type = distrf (Lib_parsing_c.ii_of_type, distribute_mck_type)
+ let distrf_param = distrf (Lib_parsing_c.ii_of_param, distribute_mck_param)
+ let distrf_params = distrf (Lib_parsing_c.ii_of_params,distribute_mck_params)
+ let distrf_ini = distrf (Lib_parsing_c.ii_of_ini,distribute_mck_ini)
+ let distrf_node = distrf (Lib_parsing_c.ii_of_node,distribute_mck_node)
+ let distrf_struct_fields =
+ distrf (Lib_parsing_c.ii_of_struct_fields, distribute_mck_struct_fields)
+ let distrf_cst =
+ distrf (Lib_parsing_c.ii_of_cst, distribute_mck_cst)
+ let distrf_define_params =
+ distrf (Lib_parsing_c.ii_of_define_params,distribute_mck_define_params)
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment *)
+ (* ------------------------------------------------------------------------*)
+ let meta_name_to_str (s1, s2) =
+ s1 ^ "." ^ s2
+
+ let envf keep _inherited = fun (s, value, _) f tin ->
+ let s = Ast_cocci.unwrap_mcode s in
+ let v =
+ if keep = Type_cocci.Saved
+ then (
+ try Some (List.assoc s tin.binding)
+ with Not_found ->
+ pr2(sprintf
+ "Don't find value for metavariable %s in the environment"
+ (meta_name_to_str s));
+ None)
+ else
+ (* not raise Impossible! *)
+ Some (value)
+ in
+ match v with
+ | None -> fail tin
+ | Some (value') ->
+
+ (* Ex: in cocci_vs_c someone wants to add a binding. Here in
+ * transformation3 the value for this var may be already in the
+ * env, because for instance its value were fixed in a previous
+ * SmPL rule. So here we want to check that this is the same value.
+ * If forget to do the check, what can happen ? Because of Exp
+ * and other disjunctive feature of cocci_vs_c (>||>), we
+ * may accept a match at a wrong position. Maybe later this
+ * will be detected via the pos system on tokens, but maybe
+ * not. So safer to keep the check.
+ *)
+
+ (*f () tin*)
+ if Cocci_vs_c_3.equal_metavarval value value'
+ then f () tin
+ else fail tin
+
+
+ let check_constraints matcher constraints exp = fun f tin -> f () tin
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment, allbounds *)
+ (* ------------------------------------------------------------------------*)
+ let (all_bound : Ast_cocci.meta_name list -> tin -> bool) = fun l tin ->
+ true (* in transform we don't care ? *)
+
+end
+
+(*****************************************************************************)
+(* Entry point *)
+(*****************************************************************************)
+module TRANS = Cocci_vs_c_3.COCCI_VS_C (XTRANS)
+
+
+let transform_re_node a b tin =
+ match TRANS.rule_elem_node a b tin with
+ | None -> raise Impossible
+ | Some (_sp, b') -> b'
+
+
+let (transform2: string (* rule name *) -> string list (* dropped_isos *) ->
+ Lib_engine.transformation_info -> F.cflow -> F.cflow) =
+ fun rule_name dropped_isos xs cflow ->
+
+ let extra = {
+ optional_storage_iso = not(List.mem "optional_storage" dropped_isos);
+ optional_qualifier_iso = not(List.mem "optional_qualifier" dropped_isos);
+ value_format_iso = not(List.mem "value_format" dropped_isos);
+ current_rule_name = rule_name;
+ } in
+
+ (* find the node, transform, update the node, and iter for all elements *)
+
+ xs +> List.fold_left (fun acc (nodei, binding, rule_elem) ->
+ (* subtil: not cflow#nodes but acc#nodes *)
+ let node = acc#nodes#assoc nodei in
+
+ if !Flag.show_misc
+ then pr2 "transform one node";
+
+ let tin = {
+ XTRANS.extra = extra;
+ XTRANS.binding = binding;
+ } in
+
+ let node' = transform_re_node rule_elem node tin in
+
+ (* assert that have done something. But with metaruleElem sometimes
+ dont modify fake nodes. So special case before on Fake nodes. *)
+ (match F.unwrap node with
+ | F.Enter | F.Exit | F.ErrorExit
+ | F.EndStatement _ | F.CaseNode _
+ | F.Fake
+ | F.TrueNode | F.FalseNode | F.AfterNode | F.FallThroughNode
+ -> ()
+ | _ -> () (* assert (not (node =*= node')); *)
+ );
+
+ (* useless, we dont go back from flow to ast now *)
+ (* let node' = lastfix_comma_struct node' in *)
+
+ acc#replace_node (nodei, node');
+ acc
+ ) cflow
+
+
+
+let transform a b c d =
+ Common.profile_code "Transformation3.transform"
+ (fun () -> transform2 a b c d)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Common
+
+module F = Control_flow_c
+
+(*****************************************************************************)
+(* The functor argument *)
+(*****************************************************************************)
+
+(* info passed recursively in monad in addition to binding *)
+type xinfo = {
+ optional_storage_iso : bool;
+ optional_qualifier_iso : bool;
+ value_format_iso : bool;
+ current_rule_name : string; (* used for errors *)
+}
+
+module XTRANS = struct
+
+ (* ------------------------------------------------------------------------*)
+ (* Combinators history *)
+ (* ------------------------------------------------------------------------*)
+ (*
+ * version0:
+ * type ('a, 'b) transformer =
+ * 'a -> 'b -> Lib_engine.metavars_binding -> 'b
+ * exception NoMatch
+ *
+ * version1:
+ * type ('a, 'b) transformer =
+ * 'a -> 'b -> Lib_engine.metavars_binding -> 'b option
+ * use an exception monad
+ *
+ * version2:
+ * type tin = Lib_engine.metavars_binding
+ *)
+
+ (* ------------------------------------------------------------------------*)
+ (* Standard type and operators *)
+ (* ------------------------------------------------------------------------*)
+
+ type tin = {
+ extra: xinfo;
+ binding: Lib_engine.metavars_binding;
+ binding0: Lib_engine.metavars_binding; (* inherited variable *)
+ }
+ type 'x tout = 'x option
+
+ type ('a, 'b) matcher = 'a -> 'b -> tin -> ('a * 'b) tout
+
+ let (>>=) m f = fun tin ->
+ match m tin with
+ | None -> None
+ | Some (a,b) -> f a b tin
+
+ let return = fun x -> fun tin ->
+ Some x
+
+ (* can have fail in transform now that the process is deterministic ? *)
+ let fail = fun tin ->
+ None
+
+ let (>||>) m1 m2 = fun tin ->
+ match m1 tin with
+ | None -> m2 tin
+ | Some x -> Some x (* stop as soon as have found something *)
+
+ let (>|+|>) m1 m2 = m1 >||> m2
+
+ let (>&&>) f m = fun tin ->
+ if f tin then m tin else fail tin
+
+ let optional_storage_flag f = fun tin ->
+ f (tin.extra.optional_storage_iso) tin
+
+ let optional_qualifier_flag f = fun tin ->
+ f (tin.extra.optional_qualifier_iso) tin
+
+ let value_format_flag f = fun tin ->
+ f (tin.extra.value_format_iso) tin
+
+ let mode = Cocci_vs_c_3.TransformMode
+
+ (* ------------------------------------------------------------------------*)
+ (* Exp *)
+ (* ------------------------------------------------------------------------*)
+ let cocciExp = fun expf expa node -> fun tin ->
+
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.kexpr_s = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | None -> (* failed *) k expb
+ | Some (x, expb) -> expb);
+ }
+ in
+ Some (expa, Visitor_c.vk_node_s bigf node)
+
+
+ (* same as cocciExp, but for expressions in an expression, not expressions
+ in a node *)
+ let cocciExpExp = fun expf expa expb -> fun tin ->
+
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.kexpr_s = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | None -> (* failed *) k expb
+ | Some (x, expb) -> expb);
+ }
+ in
+ Some (expa, Visitor_c.vk_expr_s bigf expb)
+
+
+ let cocciTy = fun expf expa node -> fun tin ->
+
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.ktype_s = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | None -> (* failed *) k expb
+ | Some (x, expb) -> expb);
+ }
+ in
+ Some (expa, Visitor_c.vk_node_s bigf node)
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Tokens *)
+ (* ------------------------------------------------------------------------*)
+ let check_pos info mck pos =
+ match mck with
+ | Ast_cocci.PLUS -> raise Impossible
+ | Ast_cocci.CONTEXT (Ast_cocci.FixPos (i1,i2),_)
+ | Ast_cocci.MINUS (Ast_cocci.FixPos (i1,i2),_) ->
+ pos <= i2 && pos >= i1
+ | Ast_cocci.CONTEXT (Ast_cocci.DontCarePos,_)
+ | Ast_cocci.MINUS (Ast_cocci.DontCarePos,_) ->
+ true
+ | _ ->
+ match info with
+ Some info ->
+ failwith
+ (Printf.sprintf
+ "wierd: dont have position info for the mcodekind in line %d column %d"
+ info.Ast_cocci.line info.Ast_cocci.column)
+ | None ->
+ failwith "wierd: dont have position info for the mcodekind"
+
+
+ let tag_with_mck mck ib = fun tin ->
+
+ let cocciinforef = ib.Ast_c.cocci_tag in
+ let (oldmcode, oldenv) = !cocciinforef in
+
+ let mck =
+ if !Flag_parsing_cocci.sgrep_mode
+ then Sgrep.process_sgrep ib mck
+ else mck
+ in
+ (match mck, Ast_c.pinfo_of_info ib with
+ | _, Ast_c.AbstractLineTok _ -> raise Impossible
+ | Ast_cocci.MINUS(_), Ast_c.ExpandedTok _ ->
+ failwith ("try to delete an expanded token: " ^ (Ast_c.str_of_info ib))
+ | _ -> ()
+ );
+
+ match (oldmcode,mck) with
+ | (Ast_cocci.CONTEXT(_,Ast_cocci.NOTHING), _)
+ | (_, Ast_cocci.CONTEXT(_,Ast_cocci.NOTHING))
+ ->
+ cocciinforef := (mck, tin.binding);
+ ib
+
+ | _ ->
+ if (oldmcode, oldenv) = (mck, tin.binding)
+ then begin
+ if !Flag.show_misc
+ then pr2 "already tagged but with same mcode, so safe";
+ ib
+ end
+ else
+ if !Flag.sgrep_mode2
+ then ib (* safe *)
+ else
+ begin
+ Format.set_formatter_out_channel stderr;
+ Common.pr2 "SP mcode ";
+ Pretty_print_cocci.print_mcodekind oldmcode;
+ Format.print_newline();
+ Common.pr2 "C code mcode ";
+ Pretty_print_cocci.print_mcodekind mck;
+ Format.print_newline();
+ Format.print_flush();
+ failwith
+ (Common.sprintf "%s: already tagged token:\n%s"
+ tin.extra.current_rule_name
+ (Common.error_message (Ast_c.file_of_info ib)
+ (Ast_c.str_of_info ib, Ast_c.opos_of_info ib)))
+ end
+
+ let tokenf ia ib = fun tin ->
+ let (_,i,mck,_) = ia in
+ let pos = Ast_c.info_to_fixpos ib in
+ if check_pos (Some i) mck pos
+ then return (ia, tag_with_mck mck ib tin) tin
+ else fail tin
+
+ let tokenf_mck mck ib = fun tin ->
+ let pos = Ast_c.info_to_fixpos ib in
+ if check_pos None mck pos
+ then return (mck, tag_with_mck mck ib tin) tin
+ else fail tin
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Distribute mcode *)
+ (* ------------------------------------------------------------------------*)
+
+ (* When in the SP we attach something to a metavariable, or delete it, as in
+ * - S
+ * + foo();
+ * we have to minusize all the token that compose S in the C code, and
+ * attach the 'foo();' to the right token, the one at the very right.
+ *)
+
+ type 'a distributer =
+ (Ast_c.info -> Ast_c.info) * (* what to do on left *)
+ (Ast_c.info -> Ast_c.info) * (* what to do on middle *)
+ (Ast_c.info -> Ast_c.info) * (* what to do on right *)
+ (Ast_c.info -> Ast_c.info) -> (* what to do on both *)
+ 'a -> 'a
+
+ let distribute_mck mcodekind distributef expr tin =
+ match mcodekind with
+ | Ast_cocci.MINUS (pos,any_xxs) ->
+ distributef (
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,any_xxs)) ib tin),
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,[])) ib tin),
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,[])) ib tin),
+ (fun ib -> tag_with_mck (Ast_cocci.MINUS (pos,any_xxs)) ib tin)
+ ) expr
+ | Ast_cocci.CONTEXT (pos,any_befaft) ->
+ (match any_befaft with
+ | Ast_cocci.NOTHING -> expr
+
+ | Ast_cocci.BEFORE xxs ->
+ distributef (
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFORE xxs)) ib tin),
+ (fun x -> x),
+ (fun x -> x),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFORE xxs)) ib tin)
+ ) expr
+ | Ast_cocci.AFTER xxs ->
+ distributef (
+ (fun x -> x),
+ (fun x -> x),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.AFTER xxs)) ib tin),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.AFTER xxs)) ib tin)
+ ) expr
+
+ | Ast_cocci.BEFOREAFTER (xxs, yys) ->
+ distributef (
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFORE xxs)) ib tin),
+ (fun x -> x),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.AFTER yys)) ib tin),
+ (fun ib -> tag_with_mck
+ (Ast_cocci.CONTEXT (pos,Ast_cocci.BEFOREAFTER (xxs,yys)))
+ ib tin)
+ ) expr
+
+ )
+ | Ast_cocci.PLUS -> raise Impossible
+
+
+ (* use new strategy, collect ii, sort, recollect and tag *)
+
+ let mk_bigf (maxpos, minpos) (lop,mop,rop,bop) =
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.kinfo_s = (fun (k,bigf) i ->
+ let pos = Ast_c.info_to_fixpos i in
+ match () with
+ | _ when Ast_cocci.equal_pos pos maxpos &&
+ Ast_cocci.equal_pos pos minpos -> bop i
+ | _ when Ast_cocci.equal_pos pos maxpos -> rop i
+ | _ when Ast_cocci.equal_pos pos minpos -> lop i
+ | _ -> mop i
+ )
+ } in
+ bigf
+
+ let distribute_mck_expr (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_expr_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_args (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_args_splitted_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_type (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_type_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_ini (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_ini_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_param (maxpos, minpos) = fun (lop,mop,rop,bop) -> fun x ->
+ Visitor_c.vk_param_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop)) x
+
+ let distribute_mck_params (maxpos, minpos) = fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_params_splitted_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let distribute_mck_node (maxpos, minpos) = fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_node_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let distribute_mck_struct_fields (maxpos, minpos) =
+ fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_struct_fields_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let distribute_mck_cst (maxpos, minpos) =
+ fun (lop,mop,rop,bop) ->fun x ->
+ Visitor_c.vk_cst_s (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+
+ let distribute_mck_define_params (maxpos, minpos) = fun (lop,mop,rop,bop) ->
+ fun x ->
+ Visitor_c.vk_define_params_splitted_s
+ (mk_bigf (maxpos, minpos) (lop,mop,rop,bop))
+ x
+
+ let get_pos mck =
+ match mck with
+ | Ast_cocci.PLUS -> raise Impossible
+ | Ast_cocci.CONTEXT (Ast_cocci.FixPos (i1,i2),_)
+ | Ast_cocci.MINUS (Ast_cocci.FixPos (i1,i2),_) ->
+ Ast_cocci.FixPos (i1,i2)
+ | Ast_cocci.CONTEXT (Ast_cocci.DontCarePos,_)
+ | Ast_cocci.MINUS (Ast_cocci.DontCarePos,_) ->
+ Ast_cocci.DontCarePos
+ | _ -> failwith "wierd: dont have position info for the mcodekind"
+
+ let distrf (ii_of_x_f, distribute_mck_x_f) =
+ fun ia x -> fun tin ->
+ let mck = Ast_cocci.get_mcodekind ia in
+ let (max, min) = Lib_parsing_c.max_min_by_pos (ii_of_x_f x)
+ in
+ if
+ (* bug: check_pos mck max && check_pos mck min
+ *
+ * if do that then if have - f(...); and in C f(1,2); then we
+ * would get a "already tagged" because the '...' would sucess in
+ * transformaing both '1' and '1,2'. So being in the range is not
+ * enough. We must be equal exactly to the range!
+ *)
+ (match get_pos mck with
+ | Ast_cocci.DontCarePos -> true
+ | Ast_cocci.FixPos (i1, i2) ->
+ i1 = min && i2 = max
+ | _ -> raise Impossible
+ )
+
+ then
+ return (
+ ia,
+ distribute_mck mck (distribute_mck_x_f (max,min)) x tin
+ ) tin
+ else fail tin
+
+
+ let distrf_e = distrf (Lib_parsing_c.ii_of_expr, distribute_mck_expr)
+ let distrf_args = distrf (Lib_parsing_c.ii_of_args, distribute_mck_args)
+ let distrf_type = distrf (Lib_parsing_c.ii_of_type, distribute_mck_type)
+ let distrf_param = distrf (Lib_parsing_c.ii_of_param, distribute_mck_param)
+ let distrf_params = distrf (Lib_parsing_c.ii_of_params,distribute_mck_params)
+ let distrf_ini = distrf (Lib_parsing_c.ii_of_ini,distribute_mck_ini)
+ let distrf_node = distrf (Lib_parsing_c.ii_of_node,distribute_mck_node)
+ let distrf_struct_fields =
+ distrf (Lib_parsing_c.ii_of_struct_fields, distribute_mck_struct_fields)
+ let distrf_cst =
+ distrf (Lib_parsing_c.ii_of_cst, distribute_mck_cst)
+ let distrf_define_params =
+ distrf (Lib_parsing_c.ii_of_define_params,distribute_mck_define_params)
+
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment *)
+ (* ------------------------------------------------------------------------*)
+ let meta_name_to_str (s1, s2) =
+ s1 ^ "." ^ s2
+
+ let envf keep _inherited = fun (s, value, _) f tin ->
+ let s = Ast_cocci.unwrap_mcode s in
+ let v =
+ if keep = Type_cocci.Saved
+ then (
+ try Some (List.assoc s tin.binding)
+ with Not_found ->
+ pr2(sprintf
+ "Don't find value for metavariable %s in the environment"
+ (meta_name_to_str s));
+ None)
+ else
+ (* not raise Impossible! *)
+ Some (value)
+ in
+ match v with
+ | None -> fail tin
+ | Some (value') ->
+
+ (* Ex: in cocci_vs_c someone wants to add a binding. Here in
+ * transformation3 the value for this var may be already in the
+ * env, because for instance its value were fixed in a previous
+ * SmPL rule. So here we want to check that this is the same value.
+ * If forget to do the check, what can happen ? Because of Exp
+ * and other disjunctive feature of cocci_vs_c (>||>), we
+ * may accept a match at a wrong position. Maybe later this
+ * will be detected via the pos system on tokens, but maybe
+ * not. So safer to keep the check.
+ *)
+
+ (*f () tin*)
+ if Cocci_vs_c_3.equal_metavarval value value'
+ then f () tin
+ else fail tin
+
+
+ let check_constraints matcher constraints exp = fun f tin -> f () tin
+
+ (* ------------------------------------------------------------------------*)
+ (* Environment, allbounds *)
+ (* ------------------------------------------------------------------------*)
+ let (all_bound : Ast_cocci.meta_name list -> tin -> bool) = fun l tin ->
+ true (* in transform we don't care ? *)
+
+end
+
+(*****************************************************************************)
+(* Entry point *)
+(*****************************************************************************)
+module TRANS = Cocci_vs_c_3.COCCI_VS_C (XTRANS)
+
+
+let transform_re_node a b tin =
+ match TRANS.rule_elem_node a b tin with
+ | None -> raise Impossible
+ | Some (_sp, b') -> b'
+
+let (transform2: string (* rule name *) -> string list (* dropped_isos *) ->
+ Lib_engine.metavars_binding (* inherited bindings *) ->
+ Lib_engine.transformation_info -> F.cflow -> F.cflow) =
+ fun rule_name dropped_isos binding0 xs cflow ->
+
+ let extra = {
+ optional_storage_iso = not(List.mem "optional_storage" dropped_isos);
+ optional_qualifier_iso = not(List.mem "optional_qualifier" dropped_isos);
+ value_format_iso = not(List.mem "value_format" dropped_isos);
+ current_rule_name = rule_name;
+ } in
+
+ (* find the node, transform, update the node, and iter for all elements *)
+
+ xs +> List.fold_left (fun acc (nodei, binding, rule_elem) ->
+ (* subtil: not cflow#nodes but acc#nodes *)
+ let node = acc#nodes#assoc nodei in
+
+ if !Flag.show_misc
+ then pr2 "transform one node";
+
+ let tin = {
+ XTRANS.extra = extra;
+ XTRANS.binding = binding0@binding;
+ XTRANS.binding0 = []; (* not used - everything constant for trans *)
+ } in
+
+ let node' = transform_re_node rule_elem node tin in
+
+ (* assert that have done something. But with metaruleElem sometimes
+ dont modify fake nodes. So special case before on Fake nodes. *)
+ (match F.unwrap node with
+ | F.Enter | F.Exit | F.ErrorExit
+ | F.EndStatement _ | F.CaseNode _
+ | F.Fake
+ | F.TrueNode | F.FalseNode | F.AfterNode | F.FallThroughNode
+ -> ()
+ | _ -> () (* assert (not (node =*= node')); *)
+ );
+
+ (* useless, we dont go back from flow to ast now *)
+ (* let node' = lastfix_comma_struct node' in *)
+
+ acc#replace_node (nodei, node');
+ acc
+ ) cflow
+
+
+
+let transform a b c d e =
+ Common.profile_code "Transformation3.transform"
+ (fun () -> transform2 a b c d e)
--- /dev/null
+.depend
+*.cma
(function
Ast.WhenNot w -> let (w,_) = get_before w [] in Ast.WhenNot w
| Ast.WhenAlways w -> let (w,_) = get_before_e w [] in Ast.WhenAlways w
- | Ast.WhenModifier(x) -> Ast.WhenModifier(x))
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x)
+ | Ast.WhenNotTrue w -> Ast.WhenNotTrue w
+ | Ast.WhenNotFalse w -> Ast.WhenNotFalse w)
wc
and get_before_e s a =
(function
Ast.WhenNot w -> let (w,_) = get_after w a (*?*) in Ast.WhenNot w
| Ast.WhenAlways w -> let (w,_) = get_after_e w a in Ast.WhenAlways w
- | Ast.WhenModifier(x) -> Ast.WhenModifier(x))
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x)
+ | Ast.WhenNotTrue w -> Ast.WhenNotTrue w
+ | Ast.WhenNotFalse w -> Ast.WhenNotFalse w)
wc
and get_after_e s a =
x::_ ->
(match Ast.unwrap x with
Ast.Atomic(x) ->
- (match Ast.unwrap x with
- Ast.Return(_,_) | Ast.ReturnExpr(_,_,_) -> true
- | _ -> false)
+ let rec loop x =
+ match Ast.unwrap x with
+ Ast.Return(_,_) | Ast.ReturnExpr(_,_,_) -> true
+ | Ast.DisjRuleElem((_::_) as l) -> List.for_all loop l
+ | _ -> false in
+ loop x
| Ast.Disj(disjs) -> List.for_all ends_in_return disjs
| _ -> false)
| _ -> false)
(wrapcode
(Ast.Continue(Ast.make_mcode "continue",Ast.make_mcode ";"))) in
let stop_early v =
- if !exists = Exists
+ if quantifier = Exists
then CTL.False
else if toend
then CTL.Or(aftpred label,exitpred label)
op s x (CTL.Let(v,y,ctl_or (CTL.Ref v) (stop_early (CTL.Ref v))))
let rec dots_and_nests plus nest whencodes bef aft dotcode after label
- process_bef_aft statement_list statement guard wrapcode =
+ process_bef_aft statement_list statement guard quantified wrapcode =
let ctl_and_ns = ctl_and CTL.NONSTRICT in
(* proces bef_aft *)
let shortest l =
if check_quantifier Ast.WhenExists Ast.WhenForall
then Exists
else
- if check_quantifier Ast.WhenExists Ast.WhenForall
+ if check_quantifier Ast.WhenForall Ast.WhenExists
then Forall
else !exists in
(* the following is used when we find a goto, etc and consider accepting
(poswhen,ctl_or (statement_list whencodes) negwhen)
| Ast.WhenAlways stm ->
(ctl_and CTL.NONSTRICT (statement stm) poswhen,negwhen)
- | Ast.WhenModifier(_) -> (poswhen,negwhen))
+ | Ast.WhenModifier(_) -> (poswhen,negwhen)
+ | Ast.WhenNotTrue(e) ->
+ (poswhen,
+ ctl_or (whencond_true e label guard quantified) negwhen)
+ | Ast.WhenNotFalse(e) ->
+ (poswhen,
+ ctl_or (whencond_false e label guard quantified) negwhen))
(CTL.True,bef_aft) (List.rev whencodes) in
let poswhen = ctl_and_ns arg poswhen in
let negwhen =
(ctl_and_ns dotcode (ctl_and_ns ornest labelled))
aft ender quantifier)
+and get_whencond_exps e =
+ match Ast.unwrap e with
+ Ast.Exp e -> [e]
+ | Ast.DisjRuleElem(res) ->
+ List.fold_left Common.union_set [] (List.map get_whencond_exps res)
+ | _ -> failwith "not possible"
+
+and make_whencond_headers e e1 label guard quantified =
+ let fvs = Ast.get_fvs e in
+ let header_pred h =
+ quantify guard (get_unquantified quantified fvs)
+ (make_match label guard h) in
+ let if_header e1 =
+ header_pred
+ (Ast.rewrap e
+ (Ast.IfHeader
+ (Ast.make_mcode "if",
+ Ast.make_mcode "(",e1,Ast.make_mcode ")"))) in
+ let while_header e1 =
+ header_pred
+ (Ast.rewrap e
+ (Ast.WhileHeader
+ (Ast.make_mcode "while",
+ Ast.make_mcode "(",e1,Ast.make_mcode ")"))) in
+ let for_header e1 =
+ header_pred
+ (Ast.rewrap e
+ (Ast.ForHeader
+ (Ast.make_mcode "for",Ast.make_mcode "(",None,Ast.make_mcode ";",
+ Some e1,Ast.make_mcode ";",None,Ast.make_mcode ")"))) in
+ let if_headers =
+ List.fold_left ctl_or CTL.False (List.map if_header e1) in
+ let while_headers =
+ List.fold_left ctl_or CTL.False (List.map while_header e1) in
+ let for_headers =
+ List.fold_left ctl_or CTL.False (List.map for_header e1) in
+ (if_headers, while_headers, for_headers)
+
+and whencond_true e label guard quantified =
+ let e1 = get_whencond_exps e in
+ let (if_headers, while_headers, for_headers) =
+ make_whencond_headers e e1 label guard quantified in
+ ctl_or
+ (ctl_and CTL.NONSTRICT (truepred label) (ctl_back_ex if_headers))
+ (ctl_and CTL.NONSTRICT
+ (inlooppred label) (ctl_back_ex (ctl_or while_headers for_headers)))
+
+and whencond_false e label guard quantified =
+ let e1 = get_whencond_exps e in
+ let (if_headers, while_headers, for_headers) =
+ make_whencond_headers e e1 label guard quantified in
+ ctl_or (ctl_and CTL.NONSTRICT (falsepred label) (ctl_back_ex if_headers))
+ (ctl_and CTL.NONSTRICT (fallpred label)
+ (ctl_or (ctl_back_ex if_headers)
+ (ctl_or (ctl_back_ex while_headers) (ctl_back_ex for_headers))))
+
(* --------------------------------------------------------------------- *)
(* the main translation loop *)
ctl_and
(quantify guard lbfvs (make_match lbrace))
(ctl_and paren_pred label_pred) in
+ let empty_rbrace =
+ match Ast.unwrap rbrace with
+ Ast.SeqEnd((data,info,_,pos)) ->
+ Ast.rewrap rbrace(Ast.SeqEnd(Ast.make_mcode data))
+ | _ -> failwith "unexpected close brace" in
let end_brace =
(* label is not needed; paren_pred is enough *)
- ctl_and
- (quantify guard rbfvs (real_make_match None guard rbrace))
- paren_pred in
+ quantify guard rbfvs
+ (ctl_au (make_match empty_rbrace)
+ (ctl_and
+ (real_make_match None guard rbrace)
+ paren_pred)) in
let new_quantified2 =
Common.union_set b1fvs (Common.union_set b2fvs quantified) in
let new_quantified3 = Common.union_set b3fvs new_quantified2 in
a goto within the current braces. checking for a goto at every
point in the pattern seems expensive and not worthwhile. *)
let pattern2 =
- let empty_rbrace =
- match Ast.unwrap rbrace with
- Ast.SeqEnd((data,info,_,pos)) ->
- Ast.rewrap rbrace(Ast.SeqEnd(Ast.make_mcode data))
- | _ -> failwith "unexpected close brace" in
let body = preprocess_dots body in (* redo, to drop braces *)
make_seq
[gotopred label;
(function x ->
statement x Tail new_quantified minus_quantified None
llabel slabel true)
- guard (function x -> Ast.set_fvs [] (Ast.rewrap stmt x)))
+ guard quantified
+ (function x -> Ast.set_fvs [] (Ast.rewrap stmt x)))
| Ast.Dots((_,i,d,_),whencodes,bef,aft) ->
let dot_code =
None llabel slabel true true)
(function x ->
statement x Tail quantified minus_quantified None llabel slabel true)
- guard (function x -> Ast.set_fvs [] (Ast.rewrap stmt x))
+ guard quantified
+ (function x -> Ast.set_fvs [] (Ast.rewrap stmt x))
| Ast.Switch(header,lb,cases,rb) ->
let rec intersect_all = function
if multi
then None (* not sure how to optimize this case *)
else Some (Common.Left stmt_dots)
- | Ast.Dots(_,whencode,_,_) -> Some (Common.Right whencode)
+ | Ast.Dots(_,whencode,_,_) when
+ (List.for_all
+ (* flow sensitive, so not optimizable *)
+ (function Ast.WhenNotTrue(_) | Ast.WhenNotFalse(_) ->
+ false
+ | _ -> true) whencode) ->
+ Some (Common.Right whencode)
| _ -> None)
| _ -> None in
let body_code =
new_quantified4 new_mquantified4
label llabel slabel true true in
ctl_or prev x
+ | Ast.WhenNotTrue(_) | Ast.WhenNotFalse(_) ->
+ failwith "unexpected"
| Ast.WhenModifier(Ast.WhenAny) -> CTL.False
| Ast.WhenModifier(_) -> prev)
CTL.False whencode))
label llabel slabel true in
ctl_and prev x
| Ast.WhenNot(sl) -> prev
+ | Ast.WhenNotTrue(_) | Ast.WhenNotFalse(_) ->
+ failwith "unexpected"
| Ast.WhenModifier(Ast.WhenAny) -> CTL.True
| Ast.WhenModifier(_) -> prev)
CTL.True whencode) in
CTL.And(CTL.NONSTRICT,
CTL.AX(CTL.FORWARD,s,CTL.AU(CTL.FORWARD,s2,e2,e3)),
CTL.EX(CTL.FORWARD,CTL.EU(CTL.FORWARD,e4,e5))))
- | CTL.AX(dir,s,CTL.XX(phi)) -> CTL.EX(dir,CTL.XX(cleanup phi))
+ | CTL.AX(dir,s,CTL.XX(phi)) -> CTL.EX(dir,cleanup phi)
| CTL.EX(dir,CTL.XX((CTL.AU(_,s,_,_)) as phi)) ->
- CTL.AX(dir,s,CTL.XX(cleanup phi))
+ CTL.AX(dir,s,cleanup phi)
| CTL.XX(phi) -> failwith "bad XX"
| CTL.AX(dir,s,phi1) -> CTL.AX(dir,s,cleanup phi1)
| CTL.AG(dir,s,phi1) -> CTL.AG(dir,s,cleanup phi1)
| A.Exp expr -> ()
| A.TopExp expr -> ()
| A.Ty ty -> ()
+ | A.TopInit init -> ()
| A.FunHeader (bef,allminus, fninfo, ida, _, paramsa, _) -> ()
| A.Decl (bef,allminus,decla) -> ()
| A.SeqStart _ -> ()
val cocciTy :
(A.fullType, B.fullType) matcher -> (A.fullType, F.node) matcher
+ val cocciInit :
+ (A.initialiser, B.initialiser) matcher -> (A.initialiser, F.node) matcher
+
val envf :
A.keep_binding -> A.inherited ->
A.meta_name A.mcode * Ast_c.metavar_binding_kind *
)
)
-
-
| A.Ty ty, nodeb ->
X.cocciTy fullType ty node >>= (fun ty node ->
return (
)
)
+ | A.TopInit init, nodeb ->
+ X.cocciInit initialiser init node >>= (fun init node ->
+ return (
+ A.TopInit init,
+ F.unwrap node
+ )
+ )
+
| A.FunHeader (mckstart, allminus, fninfoa, ida, oparen, paramsa, cparen),
F.FunHeader ((idb, (retb, (paramsb, (isvaargs, iidotsb))), stob), ii) ->
(Ast_cocci.fullType, Ast_c.fullType) matcher ->
(Ast_cocci.fullType, Control_flow_c.node) matcher
+ val cocciInit :
+ (Ast_cocci.initialiser, Ast_c.initialiser) matcher ->
+ (Ast_cocci.initialiser, Control_flow_c.node) matcher
+
(* -------------------------------------------------------------------- *)
(* Environment manipulation. Extract info from tin, the "something" *)
(* -------------------------------------------------------------------- *)
Lib_engine.model ->
(Lib_engine.ctlcocci * (pred list list)) ->
(Lib_engine.mvar list*Lib_engine.metavars_binding) ->
- (Lib_engine.transformation_info * bool * Lib_engine.metavars_binding list)) =
+ (Lib_engine.transformation_info * bool * Lib_engine.metavars_binding *
+ Lib_engine.metavars_binding list)) =
fun (flow, label, states) ctl (used_after, binding) ->
let binding2 = metavars_binding_to_binding2 binding in
let (triples,(trans_info2, returned_any_states, used_after_envs)) =
let trans_info = satbis_to_trans_info trans_info2 in
let newbindings = List.map metavars_binding2_to_binding used_after_envs in
let newbindings = List.map coalesce_positions newbindings in
- (trans_info, returned_any_states, newbindings)
+ (trans_info, returned_any_states, binding, newbindings)
let mysat a b c =
Common.profile_code "mysat" (fun () -> mysat2 a b c)
Lib_engine.model ->
(Lib_engine.ctlcocci * (pred list list)) ->
(Lib_engine.mvar list * Lib_engine.metavars_binding) ->
- (Lib_engine.transformation_info * bool * Lib_engine.metavars_binding list)
+ (Lib_engine.transformation_info * bool * Lib_engine.metavars_binding *
+ Lib_engine.metavars_binding list)
val print_bench : unit -> unit
type tin = {
extra: xinfo;
binding: Lib_engine.metavars_binding;
+ binding0: Lib_engine.metavars_binding; (* inherited bindings *)
}
(* 'x is a ('a * 'b) but in fact dont care about 'b, we just tag the SP *)
(* opti? use set instead of list *)
let (>>=) m1 m2 = fun tin ->
let xs = m1 tin in
let xxs = xs +> List.map (fun ((a,b), binding) ->
- m2 a b {extra = tin.extra; binding = binding}
+ m2 a b {tin with binding = binding}
) in
List.flatten xxs
(a, node), binding
)
+ let cocciInit = fun expf expa node -> fun tin ->
+
+ let globals = ref [] in
+ let bigf = {
+ Visitor_c.default_visitor_c with
+ Visitor_c.kini = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | [] -> (* failed *) k expb
+ | xs -> globals := xs @ !globals);
+
+ }
+ in
+ Visitor_c.vk_node bigf node;
+ !globals +> List.map (fun ((a, _exp), binding) ->
+ (a, node), binding
+ )
+
(* ------------------------------------------------------------------------*)
(* Distribute mcode *)
(fun c exp tin ->
let success = [[]] in
let failure = [] in
- (match Common.optionise (fun () -> tin.binding +> List.assoc c) with
+ (* relies on the fact that constraints on pos variables must refer to
+ inherited variables *)
+ (match Common.optionise (fun () -> tin.binding0 +> List.assoc c) with
Some valu' ->
if Cocci_vs_c_3.equal_metavarval exp valu'
then success else failure
* X et qu'elle a mis X a DontSaved.
*)
let check_add_metavars_binding strip _keep inherited = fun (k, valu) tin ->
- (match Common.optionise (fun () -> tin.binding +> List.assoc k) with
- | Some (valu') ->
- if Cocci_vs_c_3.equal_metavarval valu valu'
- then Some tin.binding
- else None
-
- | None ->
- if inherited
- then None
- else
+ if inherited
+ then
+ match Common.optionise (fun () -> tin.binding0 +> List.assoc k) with
+ | Some (valu') ->
+ if Cocci_vs_c_3.equal_metavarval valu valu'
+ then Some tin.binding
+ else None
+ | None -> None
+ else
+ match Common.optionise (fun () -> tin.binding +> List.assoc k) with
+ | Some (valu') ->
+ if Cocci_vs_c_3.equal_metavarval valu valu'
+ then Some tin.binding
+ else None
+
+ | None ->
let valu' =
match valu with
Ast_c.MetaIdVal a -> Ast_c.MetaIdVal a
| Ast_c.MetaFuncVal a -> Ast_c.MetaFuncVal a
| Ast_c.MetaLocalFuncVal a -> Ast_c.MetaLocalFuncVal a (*more?*)
| Ast_c.MetaExprVal a ->
- Ast_c.MetaExprVal
+ Ast_c.MetaExprVal
(if strip
then Lib_parsing_c.al_expr a
else Lib_parsing_c.semi_al_expr a)
| Ast_c.MetaExprListVal a ->
- Ast_c.MetaExprListVal
+ Ast_c.MetaExprListVal
(if strip
then Lib_parsing_c.al_arguments a
else Lib_parsing_c.semi_al_arguments a)
| Ast_c.MetaStmtVal a ->
- Ast_c.MetaStmtVal
+ Ast_c.MetaStmtVal
(if strip
then Lib_parsing_c.al_statement a
else Lib_parsing_c.semi_al_statement a)
| Ast_c.MetaTypeVal a ->
- Ast_c.MetaTypeVal
+ Ast_c.MetaTypeVal
(if strip
then Lib_parsing_c.al_type a
else Lib_parsing_c.semi_al_type a)
-
+
| Ast_c.MetaListlenVal a -> Ast_c.MetaListlenVal a
-
+
| Ast_c.MetaParamVal a -> failwith "not handling MetaParamVal"
| Ast_c.MetaParamListVal a ->
- Ast_c.MetaParamListVal
+ Ast_c.MetaParamListVal
(if strip
then Lib_parsing_c.al_params a
else Lib_parsing_c.semi_al_params a)
-
+
| Ast_c.MetaPosVal (pos1,pos2) -> Ast_c.MetaPosVal (pos1,pos2)
| Ast_c.MetaPosValList l -> Ast_c.MetaPosValList l
in Some (tin.binding +> Common.insert_assoc (k, valu'))
- )
let envf keep inherited = fun (k, valu, get_max_min) f tin ->
let x = Ast_cocci.unwrap_mcode k in
match check_add_metavars_binding true keep inherited (x, valu) tin with
| Some binding ->
- let new_tin = {extra = tin.extra; binding = binding} in
+ let new_tin = {tin with binding = binding} in
(match Ast_cocci.get_pos_var k with
Ast_cocci.MetaPos(name,constraints,per,keep,inherited) ->
let pvalu =
check_add_metavars_binding false keep inherited (x, pvalu)
new_tin with
| Some binding ->
- f () {extra = new_tin.extra; binding = binding}
+ f () {new_tin with binding = binding}
| None -> fail tin))
new_tin
| Ast_cocci.NoMetaPos -> f () new_tin)
let (all_bound : Ast_cocci.meta_name list -> tin -> bool) = fun l tin ->
l +> List.for_all (fun inhvar ->
- match Common.optionise (fun () -> tin.binding +> List.assoc inhvar) with
+ match Common.optionise (fun () -> tin.binding0 +> List.assoc inhvar) with
| Some _ -> true
| None -> false
)
(match
check_add_metavars_binding false keep inherited (x, pvalu) tin
with
- Some binding -> finish {extra = tin.extra; binding = binding}
+ Some binding -> finish {tin with binding = binding}
| None -> fail tin))
tin
| _ -> finish tin
module MATCH = Cocci_vs_c_3.COCCI_VS_C (XMATCH)
-let match_re_node2 dropped_isos a b binding =
+let match_re_node2 dropped_isos a b binding0 =
let tin = {
XMATCH.extra = {
optional_qualifier_iso = not(List.mem "optional_qualifier" dropped_isos);
value_format_iso = not(List.mem "value_format" dropped_isos);
};
- XMATCH.binding = binding;
+ XMATCH.binding = [];
+ XMATCH.binding0 = binding0;
} in
MATCH.rule_elem_node a b tin
type tin = {
extra: xinfo;
binding: Lib_engine.metavars_binding;
+ binding0: Lib_engine.metavars_binding; (* inherited variable *)
}
type 'x tout = 'x option
in
Some (expa, Visitor_c.vk_node_s bigf node)
+ let cocciInit = fun expf expa node -> fun tin ->
+
+ let bigf = {
+ Visitor_c.default_visitor_c_s with
+ Visitor_c.kini_s = (fun (k, bigf) expb ->
+ match expf expa expb tin with
+ | None -> (* failed *) k expb
+ | Some (x, expb) -> expb);
+ }
+ in
+ Some (expa, Visitor_c.vk_node_s bigf node)
+
(* ------------------------------------------------------------------------*)
(* Tokens *)
| None -> raise Impossible
| Some (_sp, b') -> b'
-
let (transform2: string (* rule name *) -> string list (* dropped_isos *) ->
+ Lib_engine.metavars_binding (* inherited bindings *) ->
Lib_engine.transformation_info -> F.cflow -> F.cflow) =
- fun rule_name dropped_isos xs cflow ->
+ fun rule_name dropped_isos binding0 xs cflow ->
let extra = {
optional_storage_iso = not(List.mem "optional_storage" dropped_isos);
let tin = {
XTRANS.extra = extra;
- XTRANS.binding = binding;
+ XTRANS.binding = binding0@binding;
+ XTRANS.binding0 = []; (* not used - everything constant for trans *)
} in
let node' = transform_re_node rule_elem node tin in
-let transform a b c d =
+let transform a b c d e =
Common.profile_code "Transformation3.transform"
- (fun () -> transform2 a b c d)
+ (fun () -> transform2 a b c d e)
(* note that now we do the transformation via side effect on ast *)
val transform :
string (* rule name *) -> string list (* dropped isos *) ->
+ Lib_engine.metavars_binding -> (* inherited bindings *)
Lib_engine.transformation_info ->
Control_flow_c.cflow -> Control_flow_c.cflow (* could be unit *)
--- /dev/null
+.depend
+*.cma
TARGET=extra
-SOURCES = classic_patch.ml kbuild.ml maintainers.ml c_info.ml
+SOURCES = classic_patch.ml kbuild.ml maintainers.ml
SYSLIBS = str.cma unix.cma
+++ /dev/null
-open Common
-
-open Ast_c
-
-
-(* used both for storing the entities 'defined' and 'used' in a file, but
- * depending on the use, some fields may not be used
- *)
-type entities = {
- macros: string hashset; (* object-like or function-like *)
- variables: string hashset;
- static_variables: string hashset; (* for defined only *)
- functions: string hashset;
- static_functions: string hashset; (* for defined only *)
- structs: string hashset; (* union defs, enum defs, enum values *)
- typedefs: string hashset;
- include_c: filename hashset; (* for used only *)
-}
-
-(* inverted index *)
-type idx_entities = {
- idx_macros: (string, (filename hashset)) Hashtbl.t;
- idx_variables: (string, (filename hashset)) Hashtbl.t;
- idx_functions: (string, (filename hashset)) Hashtbl.t;
- idx_structs: (string, (filename hashset)) Hashtbl.t;
- idx_typedefs: (string, (filename hashset)) Hashtbl.t;
-}
-
-let empty_entities () = {
- macros = Hashtbl.create 101;
- variables = Hashtbl.create 101;
- static_variables = Hashtbl.create 101;
- functions = Hashtbl.create 101;
- static_functions = Hashtbl.create 101;
- structs = Hashtbl.create 101;
- typedefs = Hashtbl.create 101;
- include_c = Hashtbl.create 101;
-}
-
-let empty_idx_entities () = {
- idx_macros = Hashtbl.create 101;
- idx_variables = Hashtbl.create 101;
- idx_functions = Hashtbl.create 101;
- idx_structs = Hashtbl.create 101;
- idx_typedefs = Hashtbl.create 101;
-}
-
-
-let h_to_l h = Common.hashset_to_list h
-
-let print_entities e =
- begin
-(* e.macros +> h_to_l +> List.iter (fun s -> pr("MACRO: " ^ s)); *)
- e.variables +> h_to_l +> List.iter (fun s -> pr("VAR: " ^ s));
- e.static_variables +> h_to_l +> List.iter (fun s -> pr("STATICVAR: " ^ s));
- e.functions +> h_to_l +> List.iter (fun s -> pr("FUNC: " ^ s));
- e.static_functions +> h_to_l +> List.iter (fun s -> pr("STATICFUNC: " ^ s));
- e.structs +> h_to_l +> List.iter (fun s -> pr("STRUCT: "^s));
- e.typedefs +> h_to_l +> List.iter (fun s -> pr("TYPEDEF: "^s));
- e.include_c +> h_to_l +> List.iter (fun s -> pr("INCLUDEC: "^s));
- end
-
-
-(* the defined_stuff and used_stuff may not be 100% correct. They don't handle
- * I think every dark corner of the C. It's possible to shadow in so many
- * ways.
- *)
-
-(* look only for toplevel definition *)
-let defined_stuff xs =
- let e = empty_entities() in
- let add h s = Hashtbl.add h s true in
-
- (* look only for toplevel definition: don't recurse, don't call k *)
- let bigf = { Visitor_c.default_visitor_c with
- Visitor_c.ktoplevel = (fun (k,bigf) t ->
- match t with
- | Declaration decl ->
- (match decl with
- | DeclList (xs, ii) ->
- xs +> List.iter (fun ((var, t, sto, _local), iicomma) ->
- Visitor_c.vk_type bigf t;
- match var, sto with
- | None, _ -> ()
- | Some ((s, ini), ii_s_ini), (StoTypedef,inline) ->
- add e.typedefs s;
- | Some ((s, ini), ii_s_ini), (Sto Static,inline) ->
- (* need add them to do the adjust_need *)
- add e.static_variables s;
-
- | Some ((s, ini), ii_s_ini), (Sto Extern,inline) ->
- ()
- | Some ((s, ini), ii_s_ini), (_,inline) ->
- add e.variables s;
- );
- | MacroDecl ((s, args),ii) -> ()
- )
-
- | Definition def ->
- let ((s, typ, sto, cp), ii) = def in
- (match sto with
- | Sto Static, inline ->
- (* need add them to do the adjust_need *)
- add e.static_functions s
- | _ ->
- add e.functions s
- )
-
- | Include includ -> ()
- | Define ((s,ii), body) -> add e.macros s
- | MacroTop (s, args, ii) -> ()
-
- | EmptyDef _ | NotParsedCorrectly _ | FinalDef _ -> ()
- );
-
- Visitor_c.ktype = (fun (k, bigf) t ->
- match Ast_c.unwrap_typeC t with
- | StructUnion (su, sopt, fields) ->
- sopt +> do_option (fun s ->
- add e.structs s;
- );
-
- | _ -> ()
- );
-
- } in
- xs +> List.iter (fun (p, info_item) -> Visitor_c.vk_toplevel bigf p);
- e
-
-
-
-
-
-
-
-
-(* look only for use of external stuff. Don't consider local vars,
- * typedefs, structures *)
-let used_stuff xs =
-
- let e = empty_entities() in
- let add h s = Hashtbl.replace h s true in
-
- let initial_env = [
- ["NULL";
- "do_gettimeofday";
- "le32_to_cpu";
- "udelay";
- "printk";
- (* !!! sometimes considered as VAR :( *)
- "u8"; "u16"; "u32";
- "s32";
- ] +> List.map (fun s -> s, true);
- ]
- in
- let regexp_macro = Str.regexp
- "^[A-Z_][A-Z_0-9]*$"
- in
-
- let (_env: (string, bool) Common.scoped_env ref) = ref initial_env in
-
-
- let bigf = { Visitor_c.default_visitor_c with
-
- (* --------- handling scope of variables (and also some use) --------- *)
- Visitor_c.kstatement = (fun (k, bigf) st ->
- match st with
- | Compound statxs, ii -> Common.do_in_new_scope _env (fun () -> k st);
- | _ -> k st
- );
- Visitor_c.kdecl = (fun (k, bigf) d ->
- k d; (* to add possible definition in type found in Decl *)
- (match d with
- | (DeclList (xs, ii)) ->
- xs +> List.iter (fun ((var, t, sto, _local), iicomma) ->
- var +> do_option (fun ((s, ini), ii_s_ini) ->
- match sto with
- | StoTypedef, _inline ->
- (* add_binding (TypeDef (s)) true; *)
- ()
- | _ ->
- Common.add_in_scope _env (s, true);
- );
- );
- | _ -> ()
- );
- );
- Visitor_c.ktoplevel = (fun (k, bigf) elem ->
- match elem with
- | Definition def ->
- let (funcs, ((returnt, (paramst, b))), sto, statxs),ii = def in
- Common.do_in_new_scope _env (fun () ->
- paramst +> List.iter (fun (((b, s, t), _),_) ->
- match s with
- | Some s -> Common.add_in_scope _env (s, true)
- | None -> pr2 "no type, certainly because Void type ?"
- );
- k elem
- );
- | Define (s, (defkind, defval)) ->
- Common.do_in_new_scope _env (fun () ->
- (match defkind with
- | DefineFunc (params, ii) ->
- params +> List.iter (fun ((s,iis), iicomma) ->
- Common.add_in_scope _env (s, true)
- );
- | _ -> ()
- );
- k elem
- );
- | Include ((inc_file,ii), posref) ->
- (match inc_file with
- | Local [x] when x =~ ".*\\.c$" ->
- add e.include_c x
- | _ -> ()
- )
- | _ -> k elem
- );
-
-
- (* --------- and now looking for use --------- *)
- Visitor_c.kexpr = (fun (k,bigf) x ->
- match Ast_c.unwrap_expr x with
-
- | FunCall (((Ident f, typ), ii), args) ->
- if not (Common.member_env_key f !_env)
- then
- if f ==~ regexp_macro
- then add e.macros f
- else add e.functions f
- ;
- args +> List.iter (fun (x,ii) ->
- Visitor_c.vk_argument bigf x
- );
- | Ident s ->
- if not (Common.member_env_key s !_env)
- then
- if s ==~ regexp_macro
- then add e.macros s
- else add e.variables s
-
- | _ -> k x
- );
-
- Visitor_c.ktype = (fun (k,bigf) t ->
- match Ast_c.unwrap_typeC t with
- | StructUnionName (su, s) ->
- if not (Common.member_env_key s !_env)
- then
- add e.structs s;
- | TypeName (s,_typ) ->
- if not (Common.member_env_key s !_env)
- then
- add e.typedefs s;
- | _ -> k t
- );
-
- } in
- xs +> List.iter (fun (p, info_item) -> Visitor_c.vk_toplevel bigf p);
- e
-
-
-
-
-(* for the moment, just look if it looks like a linux module file *)
-let extra_stuff xs =
- let is_module = ref false in
-
- (* look only for toplevel definition: don't recurse, don't call k *)
- let bigf = { Visitor_c.default_visitor_c with
- Visitor_c.ktoplevel = (fun (k,bigf) t ->
- match t with
- | MacroTop (s, args, ii) ->
- if s = "module_init"
- then is_module := true;
- | Definition def ->
- let ((s, typ, sto, cp), ii) = def in
- if s = "init_module"
- then is_module := true;
-
- | _ -> ()
- );
- } in
- xs +> List.iter (fun (p, info_item) -> Visitor_c.vk_toplevel bigf p);
- !is_module
-
-
-
-let adjust_used_only_external used defined =
- begin
- used.variables +> h_to_l +> List.iter (fun s ->
- if Hashtbl.mem defined.variables s ||
- Hashtbl.mem defined.static_variables s ||
- (* sometimes functions are used as variable, when for example
- * stored in a pointer variable, so look also for function here.
- *)
- Hashtbl.mem defined.functions s ||
- Hashtbl.mem defined.static_functions s
- then Hashtbl.remove used.variables s
- );
- used.functions +> h_to_l +> List.iter (fun s ->
- if Hashtbl.mem defined.functions s ||
- Hashtbl.mem defined.static_functions s
- then Hashtbl.remove used.functions s
- );
- used.structs +> h_to_l +> List.iter (fun s ->
- if Hashtbl.mem defined.structs s
- then Hashtbl.remove used.structs s
- );
- used.typedefs +> h_to_l +> List.iter (fun s ->
- if Hashtbl.mem defined.typedefs s
- then Hashtbl.remove used.typedefs s
- );
- end
-
-
-
-
-type file_info = {
- used: entities;
- defined: entities;
- is_module: bool;
-}
-type global_definitions = idx_entities
-
-let mk_global_definitions_index xs =
- let idx = empty_idx_entities () in
- xs +> List.iter (fun (file, {defined = defined}) ->
- defined.variables +> h_to_l +> List.iter (fun s ->
- Common.hash_hashset_add s file idx.idx_variables;
- );
- defined.functions +> h_to_l +> List.iter (fun s ->
- Common.hash_hashset_add s file idx.idx_functions;
- );
- defined.structs +> h_to_l +> List.iter (fun s ->
- Common.hash_hashset_add s file idx.idx_structs;
- );
- defined.typedefs +> h_to_l +> List.iter (fun s ->
- Common.hash_hashset_add s file idx.idx_typedefs;
- );
- );
- idx
-
-let known_duplicate =
- ["init_module"; "cleanup_module";
- "main";"usage";
- ]
-
-let check_no_duplicate_global_definitions idx =
- begin
- pr2 "DUPLICATE processing:";
- idx.idx_functions +> hash_to_list +> List.iter (fun (f, set) ->
- let xs = hash_to_list set in
- if List.length xs <> 1 && not (List.mem f known_duplicate)
- then
- pr2 ("multiple def for : " ^ f ^ " in " ^
- (join " " (List.map (fun x -> basename (fst x)) xs)));
- );
- end
-
-type dependencies_graph =
- ((filename * file_info) * string, bool) Ograph_extended.ograph_mutable
-
-
-let build_graph xs dep graphfile =
- let g = ref (new Ograph_extended.ograph_mutable) in
- let h = Hashtbl.create 101 in
- let s_to_nodei s = Hashtbl.find h s in
-
- pr2 "BUILDING graph:";
-
- let arrow a b c d =
- (sprintf "%-20s -- %s:%25s --> %s" a b c d)
- in
- with_open_outfile (graphfile ^ ".graph") (fun (pr_no_nl,chan) ->
- let pr_arrow a b c d =
- pr2 (arrow a b c d);
- pr_no_nl (arrow a b c d ^ "\n");
- in
-
- (* build nodes *)
- xs +> List.iter (fun (file, cinfo) ->
- let s = (if cinfo.is_module then "[M]" else "") ^ Filename.basename file in
- let xi = !g#add_node ((file, cinfo), s) in
- Hashtbl.add h file xi;
- );
-
- xs +> List.iter (fun (file, {used = used}) ->
-
- used.functions +> h_to_l +> List.iter (fun s ->
- match Common.optionise (fun () -> Hashtbl.find dep.idx_functions s) with
- | None -> ()
- | Some hset ->
- hset +> h_to_l +> List.iter (fun file_defined ->
- !g#add_arc ((s_to_nodei file, s_to_nodei file_defined), true);
- let (file, file_defined) = basename file, basename file_defined in
- pr_arrow file "f" s file_defined;
- );
- );
- (* sometime use functions as variable *)
- used.variables +> h_to_l +> List.iter (fun s ->
- match Common.optionise (fun () -> Hashtbl.find dep.idx_functions s) with
- | None -> ()
- | Some hset ->
- hset +> h_to_l +> List.iter (fun file_defined ->
- !g#add_arc ((s_to_nodei file, s_to_nodei file_defined), true);
- let (file, file_defined) = basename file, basename file_defined in
- pr_arrow file "f" s file_defined;
- );
- );
-
- used.variables +> h_to_l +> List.iter (fun s ->
- match Common.optionise (fun () -> Hashtbl.find dep.idx_variables s) with
- | None -> ()
- | Some hset ->
- hset +> h_to_l +> List.iter (fun file_defined ->
- !g#add_arc ((s_to_nodei file, s_to_nodei file_defined), true);
- let (file, file_defined) = basename file, basename file_defined in
- pr_arrow file "v" s file_defined;
- );
- );
-
- used.include_c +> h_to_l +> List.iter (fun local_file ->
- let file_defined = Filename.concat (dirname file) local_file in
- try (
- !g#add_arc ((s_to_nodei file, s_to_nodei file_defined), true);
- let (file, file_defined) = basename file, basename file_defined in
- pr_arrow file "I" "include" file_defined;
- )
- with Not_found ->
- pr2 ("can't find included C file: " ^ file_defined)
- )
-
-(*
- used.structs +> h_to_l +> List.iter (fun s ->
- match Common.optionise (fun () -> Hashtbl.find dep.idx_structs s) with
- | None -> ()
- | Some hset ->
- hset +> h_to_l +> List.iter (fun file_defined ->
- !g#add_arc ((s_to_nodei file, s_to_nodei file_defined), true);
- );
- );
-
- used.typedefs +> h_to_l +> List.iter (fun s ->
- match Common.optionise (fun () -> Hashtbl.find dep.idx_typedefs s) with
- | None -> ()
- | Some hset ->
- hset +> h_to_l +> List.iter (fun file_defined ->
- !g#add_arc ((s_to_nodei file, s_to_nodei file_defined), true);
- );
- );
-*)
- );
- );
- Ograph_extended.print_ograph_mutable !g graphfile (!Flag.show_misc);
- !g
-
-
-
-
-
-let generate_makefile (g: dependencies_graph) file =
- pr2 "GENERATING makefile";
- with_open_outfile file (fun (pr_no_nl, chan) ->
-
- let nodei_to_file xi =
- let ((file, cinfo ), s) = (g#nodes#assoc xi) in
- file
- in
- let all_nodes = g#nodes#tolist +> List.map fst in
- let visited_nodes_h = Hashtbl.create 101 in
-
- let modules = all_nodes +> List.filter (fun xi ->
- let ((file, cinfo), s) = g#nodes#assoc xi in
- cinfo.is_module
- ) in
-
- pr_no_nl " # ---- modules files ---- \n";
- modules +> List.iter (fun xi ->
- pr2 (nodei_to_file xi);
- pr_no_nl " ";
- g +> Ograph_extended.dfs_iter xi (fun yi ->
- pr2 (" " ^ (Filename.basename (nodei_to_file yi)));
- pr_no_nl (" " ^ (Filename.basename (nodei_to_file yi)));
- Hashtbl.add visited_nodes_h yi true;
- );
- pr_no_nl "\n";
- );
- let visited_nodes = Common.hashset_to_list visited_nodes_h in
- let rest = all_nodes $-$ visited_nodes in
-
- let startfiles = rest +> List.filter (fun xi ->
- (g#predecessors xi)#null
- ) in
- pr_no_nl " # ---- not module starting files ---- \n";
-
- startfiles +> List.iter (fun xi ->
- pr2 (nodei_to_file xi);
- pr_no_nl " ";
- g +> Ograph_extended.dfs_iter xi (fun yi ->
- pr2 (" " ^ (Filename.basename (nodei_to_file yi)));
- pr_no_nl (" " ^ (Filename.basename (nodei_to_file yi)));
- Hashtbl.add visited_nodes_h yi true;
- );
- pr_no_nl "\n";
- );
- let visited_nodes = Common.hashset_to_list visited_nodes_h in
- let rest = rest $-$ visited_nodes in
-
- if not (null rest) then pr_no_nl " # ---- files in cycle ---- \n";
- rest +> List.iter (fun xi ->
- if Hashtbl.mem visited_nodes_h xi then () (* already handled *)
- else begin
- pr2 (nodei_to_file xi);
- pr_no_nl " ";
- g +> Ograph_extended.dfs_iter xi (fun yi ->
- pr2 (" " ^ (Filename.basename (nodei_to_file yi)));
- pr_no_nl (" " ^ (Filename.basename (nodei_to_file yi)));
- Hashtbl.add visited_nodes_h yi true;
- );
- pr_no_nl "\n";
- end
- )
- )
-
+++ /dev/null
-open Common
-
-type entities = {
- macros : string hashset;
- variables : string hashset;
- static_variables : string hashset;
- functions : string hashset;
- static_functions : string hashset;
- structs : string hashset;
- typedefs : string hashset;
- include_c : filename hashset;
-}
-val print_entities : entities -> unit
-
-type idx_entities = {
- idx_macros : (string, filename hashset) Hashtbl.t;
- idx_variables : (string, filename hashset) Hashtbl.t;
- idx_functions : (string, filename hashset) Hashtbl.t;
- idx_structs : (string, filename hashset) Hashtbl.t;
- idx_typedefs : (string, filename hashset) Hashtbl.t;
-}
-
-type file_info = {
- used : entities;
- defined : entities;
- is_module : bool;
-}
-
-type global_definitions = idx_entities
-
-type dependencies_graph =
- ((filename * file_info) * string, bool) Ograph_extended.ograph_mutable
-
-
-val defined_stuff : (Ast_c.toplevel * 'a) list -> entities
-val used_stuff : (Ast_c.toplevel * 'a) list -> entities
-(* is_module *)
-val extra_stuff : (Ast_c.toplevel * 'a) list -> bool
-
-val adjust_used_only_external : entities -> entities -> unit
-
-val mk_global_definitions_index :
- (filename * file_info) list -> idx_entities
-val check_no_duplicate_global_definitions :
- idx_entities -> unit
-
-
-val build_graph :
- (filename * file_info) list -> idx_entities -> filename (*outfile*) ->
- ((filename * file_info) * string, bool) Ograph_extended.ograph_mutable
-
-
-val generate_makefile : dependencies_graph -> filename -> unit
(* the "underived" outputs *)
let show_transinfo = ref true
let show_binding_in_out = ref false
+let show_dependencies = ref false
let windows = ref false
--- /dev/null
+.depend
+*.cma
-let version = "0.1"
+let version = "0.1.1"
let path =
try (Sys.getenv "COCCINELLE_HOME")
" guess what";
"-date", Arg.Unit (fun () ->
- pr2 "version: $Date: 2008/09/26 00:44:57 $";
+ pr2 "version: $Date: 2008/10/11 16:22:38 $";
raise (Common.UnixExit 0)
),
" guess what";
"-no_show_misc", Arg.Clear Flag.show_misc, " ";
"-show_trying", Arg.Set Flag.show_trying,
" show the name of each function being processed";
+ "-show_dependencies",
+ Arg.Unit (function _ -> Flag_cocci.show_dependencies := true;
+ Flag_cocci.show_binding_in_out := true),
+ " show the dependencies related to each rule";
];
"verbose subsystems options",
--- /dev/null
+.depend
+*.cma
--- /dev/null
+.depend
+*.cma
+lexer_c.ml
+parser_c.ml
+parser_c.mli
+parser_c.output
| Ast.Exp(exp) -> print_string arity; expression exp
| Ast.TopExp(exp) -> print_string arity; expression exp
| Ast.Ty(ty) -> print_string arity; fullType ty
+ | Ast.TopInit(init) -> initialiser false init
| Ast.Include(inc,s) ->
mcode print_string inc; print_string " "; mcode inc_file s
| Ast.DefineHeader(def,id,params) ->
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Arities matter for the minus slice, but not for the plus slice. *)
+
+(* ? only allowed on rule_elems, and on subterms if the context is ? also. *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+
+(* --------------------------------------------------------------------- *)
+
+let warning s = Printf.printf "warning: %s\n" s
+
+let fail w str =
+ failwith
+ (Printf.sprintf "cocci line %d: %s" ((Ast0.get_info w).Ast0.line_start)
+ str)
+
+let make_opt_unique optfn uniquefn info tgt arity term =
+ let term = Ast0.rewrap info term in
+ if tgt = arity
+ then term
+ else (* tgt must be NONE *)
+ match arity with
+ Ast0.OPT -> Ast0.copywrap info (optfn term)
+ | Ast0.UNIQUE -> Ast0.copywrap info (uniquefn term)
+ | Ast0.NONE -> failwith "tgt must be NONE"
+
+let all_same opt_allowed tgt line arities =
+ let tgt =
+ match tgt with
+ Ast0.NONE ->
+ (match List.hd arities with
+ Ast0.OPT when not opt_allowed ->
+ failwith "opt only allowed for the elements of a statement list"
+ | x -> x)
+ | _ -> tgt in
+ if not(List.for_all (function x -> x = tgt) arities)
+ then warning (Printf.sprintf "incompatible arity found on line %d" line);
+ tgt
+
+let get_option fn = function
+ None -> None
+ | Some x -> Some (fn x)
+
+let anyopt l fn = List.exists (function w -> fn(Ast0.unwrap w)) l
+
+let allopt l fn =
+ let rec loop = function
+ [] -> []
+ | x::xs ->
+ match fn (Ast0.unwrap x) with
+ Some x -> x :: (loop xs)
+ | None -> [] in
+ let res = loop l in
+ if List.length res = List.length l then Some res else None
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Mcode *)
+
+let mcode2line (_,_,info,_,_) = info.Ast0.line_start
+let mcode2arity (_,arity,_,_,_) = arity
+
+let mcode x = x (* nothing to do ... *)
+
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots fn d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) -> Ast0.DOTS(List.map fn x)
+ | Ast0.CIRCLES(x) -> Ast0.CIRCLES(List.map fn x)
+ | Ast0.STARS(x) -> Ast0.STARS(List.map fn x))
+
+let only_dots l =
+ not
+ (List.exists
+ (function x ->
+ match Ast0.unwrap x with
+ Ast0.Circles(_,_) | Ast0.Stars(_,_) -> true
+ | _ -> false)
+ l)
+
+let only_circles l =
+ not (List.exists
+ (function x ->
+ match Ast0.unwrap x with
+ Ast0.Dots(_,_) | Ast0.Stars(_,_) -> true
+ | _ -> false)
+ l)
+
+let only_stars l =
+ not (List.exists
+ (function x ->
+ match Ast0.unwrap x with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) -> true
+ | _ -> false)
+ l)
+
+let concat_dots fn d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) ->
+ let l = List.map fn x in
+ if only_dots l
+ then Ast0.DOTS(l)
+ else fail d "inconsistent dots usage"
+ | Ast0.CIRCLES(x) ->
+ let l = List.map fn x in
+ if only_circles l
+ then Ast0.CIRCLES(l)
+ else fail d "inconsistent dots usage"
+ | Ast0.STARS(x) ->
+ let l = List.map fn x in
+ if only_stars l
+ then Ast0.STARS(l)
+ else fail d "inconsistent dots usage")
+
+let flat_concat_dots fn d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> List.map fn x
+ | Ast0.CIRCLES(x) -> List.map fn x
+ | Ast0.STARS(x) -> List.map fn x
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let make_id =
+ make_opt_unique
+ (function x -> Ast0.OptIdent x)
+ (function x -> Ast0.UniqueIdent x)
+
+let ident opt_allowed tgt i =
+ match Ast0.unwrap i with
+ Ast0.Id(name) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.Id(name))
+ | Ast0.MetaId(name,constraints,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.MetaId(name,constraints,pure))
+ | Ast0.MetaFunc(name,constraints,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.MetaFunc(name,constraints,pure))
+ | Ast0.MetaLocalFunc(name,constraints,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.MetaLocalFunc(name,constraints,pure))
+ | Ast0.OptIdent(_) | Ast0.UniqueIdent(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let make_exp =
+ make_opt_unique
+ (function x -> Ast0.OptExp x)
+ (function x -> Ast0.UniqueExp x)
+
+let rec top_expression opt_allowed tgt expr =
+ let exp_same = all_same opt_allowed tgt in
+ match Ast0.unwrap expr with
+ Ast0.Ident(id) ->
+ let new_id = ident opt_allowed tgt id in
+ Ast0.rewrap expr
+ (match Ast0.unwrap new_id with
+ Ast0.OptIdent(id) ->
+ Ast0.OptExp(Ast0.rewrap expr (Ast0.Ident(id)))
+ | Ast0.UniqueIdent(id) ->
+ Ast0.UniqueExp(Ast0.rewrap expr (Ast0.Ident(id)))
+ | _ -> Ast0.Ident(new_id))
+ | Ast0.Constant(const) ->
+ let arity = exp_same (mcode2line const) [mcode2arity const] in
+ let const = mcode const in
+ make_exp expr tgt arity (Ast0.Constant(const))
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let fn = expression arity fn in
+ let lp = mcode lp in
+ let args = dots (expression arity) args in
+ let rp = mcode rp in
+ make_exp expr tgt arity (Ast0.FunCall(fn,lp,args,rp))
+ | Ast0.Assignment(left,op,right,simple) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let left = expression arity left in
+ let op = mcode op in
+ let right = expression arity right in
+ make_exp expr tgt arity (Ast0.Assignment(left,op,right,simple))
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ let arity =
+ exp_same (mcode2line why) [mcode2arity why; mcode2arity colon] in
+ let exp1 = expression arity exp1 in
+ let why = mcode why in
+ let exp2 = get_option (expression arity) exp2 in
+ let colon = mcode colon in
+ let exp3 = expression arity exp3 in
+ make_exp expr tgt arity (Ast0.CondExpr(exp1,why,exp2,colon,exp3))
+ | Ast0.Postfix(exp,op) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let exp = expression arity exp in
+ let op = mcode op in
+ make_exp expr tgt arity (Ast0.Postfix(exp,op))
+ | Ast0.Infix(exp,op) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let exp = expression arity exp in
+ let op = mcode op in
+ make_exp expr tgt arity (Ast0.Infix(exp,op))
+ | Ast0.Unary(exp,op) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let exp = expression arity exp in
+ let op = mcode op in
+ make_exp expr tgt arity (Ast0.Unary(exp,op))
+ | Ast0.Binary(left,op,right) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let left = expression arity left in
+ let op = mcode op in
+ let right = expression arity right in
+ make_exp expr tgt arity (Ast0.Binary(left,op,right))
+ | Ast0.Nested(left,op,right) -> failwith "nested in arity not possible"
+ | Ast0.Paren(lp,exp,rp) ->
+ let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ make_exp expr tgt arity (Ast0.Paren(lp,exp,rp))
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ let arity = exp_same (mcode2line lb) [mcode2arity lb; mcode2arity rb] in
+ let exp1 = expression arity exp1 in
+ let lb = mcode lb in
+ let exp2 = expression arity exp2 in
+ let rb = mcode rb in
+ make_exp expr tgt arity (Ast0.ArrayAccess(exp1,lb,exp2,rb))
+ | Ast0.RecordAccess(exp,pt,field) ->
+ let arity = exp_same (mcode2line pt) [mcode2arity pt] in
+ let exp = expression arity exp in
+ let pt = mcode pt in
+ let field = ident false arity field in
+ make_exp expr tgt arity (Ast0.RecordAccess(exp,pt,field))
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ let arity = exp_same (mcode2line ar) [mcode2arity ar] in
+ let exp = expression arity exp in
+ let ar = mcode ar in
+ let field = ident false arity field in
+ make_exp expr tgt arity (Ast0.RecordPtAccess(exp,ar,field))
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let lp = mcode lp in
+ let ty = typeC arity ty in
+ let rp = mcode rp in
+ let exp = expression arity exp in
+ make_exp expr tgt arity (Ast0.Cast(lp,ty,rp,exp))
+ | Ast0.SizeOfExpr(szf,exp) ->
+ let arity = exp_same (mcode2line szf) [mcode2arity szf] in
+ let szf = mcode szf in
+ let exp = expression arity exp in
+ make_exp expr tgt arity (Ast0.SizeOfExpr(szf,exp))
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ let arity =
+ exp_same (mcode2line szf) (List.map mcode2arity [szf;lp;rp]) in
+ let szf = mcode szf in
+ let lp = mcode lp in
+ let ty = typeC arity ty in
+ let rp = mcode rp in
+ make_exp expr tgt arity (Ast0.SizeOfType(szf,lp,ty,rp))
+ | Ast0.TypeExp(ty) -> Ast0.rewrap expr (Ast0.TypeExp(typeC tgt ty))
+ | Ast0.MetaErr(name,constraints,pure) ->
+ let arity = exp_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_exp expr tgt arity (Ast0.MetaErr(name,constraints,pure))
+ | Ast0.MetaExpr(name,constraints,ty,form,pure) ->
+ let arity = exp_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_exp expr tgt arity (Ast0.MetaExpr(name,constraints,ty,form,pure))
+ | Ast0.MetaExprList(name,lenname,pure) ->
+ let arity = exp_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_exp expr tgt arity (Ast0.MetaExprList(name,lenname,pure))
+ | Ast0.EComma(cm) ->
+ let arity = exp_same (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_exp expr tgt arity (Ast0.EComma(cm))
+ | Ast0.DisjExpr(starter,exps,mids,ender) ->
+ let exps = List.map (top_expression opt_allowed tgt) exps in
+ (match List.rev exps with
+ _::xs ->
+ if anyopt xs (function Ast0.OptExp(_) -> true | _ -> false)
+ then fail expr "opt only allowed in the last disjunct"
+ | _ -> ());
+ Ast0.rewrap expr (Ast0.DisjExpr(starter,exps,mids,ender))
+ | Ast0.NestExpr(starter,exp_dots,ender,whencode,multi) ->
+ let res =
+ Ast0.NestExpr(starter,
+ dots (top_expression true Ast0.NONE) exp_dots,
+ ender,whencode,multi) in
+ Ast0.rewrap expr res
+ | Ast0.Edots(dots,whencode) ->
+ let arity = exp_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (expression Ast0.NONE) whencode in
+ make_exp expr tgt arity (Ast0.Edots(dots,whencode))
+ | Ast0.Ecircles(dots,whencode) ->
+ let arity = exp_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (expression Ast0.NONE) whencode in
+ make_exp expr tgt arity (Ast0.Ecircles(dots,whencode))
+ | Ast0.Estars(dots,whencode) ->
+ let arity = exp_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (expression Ast0.NONE) whencode in
+ make_exp expr tgt arity (Ast0.Estars(dots,whencode))
+ | Ast0.OptExp(_) | Ast0.UniqueExp(_) ->
+ failwith "unexpected code"
+
+and expression tgt exp = top_expression false tgt exp
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and make_typeC =
+ make_opt_unique
+ (function x -> Ast0.OptType x)
+ (function x -> Ast0.UniqueType x)
+
+and top_typeC tgt opt_allowed typ =
+ match Ast0.unwrap typ with
+ Ast0.ConstVol(cv,ty) ->
+ let arity = all_same opt_allowed tgt (mcode2line cv)
+ [mcode2arity cv] in
+ let cv = mcode cv in
+ let ty = typeC arity ty in
+ make_typeC typ tgt arity (Ast0.ConstVol(cv,ty))
+ | Ast0.BaseType(ty,Some sign) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line ty)
+ [mcode2arity ty; mcode2arity sign] in
+ let ty = mcode ty in
+ let sign = mcode sign in
+ make_typeC typ tgt arity (Ast0.BaseType(ty,Some sign))
+ | Ast0.BaseType(ty,None) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line ty) [mcode2arity ty] in
+ let ty = mcode ty in
+ make_typeC typ tgt arity (Ast0.BaseType(ty,None))
+ | Ast0.ImplicitInt(sign) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line sign) [mcode2arity sign] in
+ let sign = mcode sign in
+ make_typeC typ tgt arity (Ast0.ImplicitInt(sign))
+ | Ast0.Pointer(ty,star) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line star) [mcode2arity star] in
+ let ty = typeC arity ty in
+ let star = mcode star in
+ make_typeC typ tgt arity (Ast0.Pointer(ty,star))
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lp1)
+ (List.map mcode2arity [lp1;star;rp1;lp2;rp2]) in
+ let ty = typeC arity ty in
+ let params = parameter_list tgt params in
+ make_typeC typ tgt arity
+ (Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2))
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lp1)
+ (List.map mcode2arity [lp1;rp1]) in
+ let ty = get_option (typeC arity) ty in
+ let params = parameter_list tgt params in
+ make_typeC typ tgt arity (Ast0.FunctionType(ty,lp1,params,rp1))
+ | Ast0.Array(ty,lb,size,rb) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lb)
+ [mcode2arity lb;mcode2arity rb] in
+ let ty = typeC arity ty in
+ let lb = mcode lb in
+ let size = get_option (expression arity) size in
+ let rb = mcode rb in
+ make_typeC typ tgt arity (Ast0.Array(ty,lb,size,rb))
+ | Ast0.StructUnionName(kind,name) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line kind)
+ [mcode2arity kind] in
+ let kind = mcode kind in
+ let name = get_option (ident false arity) name in
+ make_typeC typ tgt arity (Ast0.StructUnionName(kind,name))
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lb)
+ (List.map mcode2arity [lb;rb]) in
+ let ty = typeC arity ty in
+ let lb = mcode lb in
+ let decls = dots (declaration tgt) decls in
+ let rb = mcode rb in
+ make_typeC typ tgt arity (Ast0.StructUnionDef(ty,lb,decls,rb))
+ | Ast0.TypeName(name) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_typeC typ tgt arity (Ast0.TypeName(name))
+ | Ast0.MetaType(name,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_typeC typ tgt arity (Ast0.MetaType(name,pure))
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ let types = List.map (typeC tgt) types in
+ (match List.rev types with
+ _::xs ->
+ if anyopt xs (function Ast0.OptType(_) -> true | _ -> false)
+ then fail typ "opt only allowed in the last disjunct"
+ | _ -> ());
+ let res = Ast0.DisjType(starter,types,mids,ender) in
+ Ast0.rewrap typ res
+ | Ast0.OptType(_) | Ast0.UniqueType(_) ->
+ failwith "unexpected code"
+
+and typeC tgt ty = top_typeC tgt false ty
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and make_decl =
+ make_opt_unique
+ (function x -> Ast0.OptDecl x)
+ (function x -> Ast0.UniqueDecl x)
+
+and declaration tgt decl =
+ match Ast0.unwrap decl with
+ Ast0.Init(stg,ty,id,eq,exp,sem) ->
+ let arity =
+ all_same true tgt (mcode2line eq)
+ ((match stg with None -> [] | Some x -> [mcode2arity x]) @
+ (List.map mcode2arity [eq;sem])) in
+ let stg = get_option mcode stg in
+ let ty = typeC arity ty in
+ let id = ident false arity id in
+ let eq = mcode eq in
+ let exp = initialiser arity exp in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.Init(stg,ty,id,eq,exp,sem))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ let arity =
+ all_same true tgt (mcode2line sem)
+ ((match stg with None -> [] | Some x -> [mcode2arity x]) @
+ [mcode2arity sem]) in
+ let stg = get_option mcode stg in
+ let ty = typeC arity ty in
+ let id = ident false arity id in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.UnInit(stg,ty,id,sem))
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ let arity =
+ all_same true tgt (mcode2line lp) (List.map mcode2arity [lp;rp;sem]) in
+ let name = ident false arity name in
+ let lp = mcode lp in
+ let args = dots (expression arity) args in
+ let rp = mcode rp in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.MacroDecl(name,lp,args,rp,sem))
+ | Ast0.TyDecl(ty,sem) ->
+ let arity =
+ all_same true tgt (mcode2line sem) [mcode2arity sem] in
+ let ty = typeC arity ty in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.TyDecl(ty,sem))
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ let arity =
+ all_same true tgt (mcode2line sem)
+ [mcode2arity stg;mcode2arity sem] in
+ let stg = mcode stg in
+ let ty = typeC arity ty in
+ let id = typeC arity id in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.Typedef(stg,ty,id,sem))
+ | Ast0.DisjDecl(starter,decls,mids,ender) ->
+ let decls = List.map (declaration tgt) decls in
+ (match List.rev decls with
+ _::xs ->
+ if anyopt xs (function Ast0.OptDecl(_) -> true | _ -> false)
+ then fail decl "opt only allowed in the last disjunct"
+ | _ -> ());
+ let res = Ast0.DisjDecl(starter,decls,mids,ender) in
+ Ast0.rewrap decl res
+ | Ast0.Ddots(dots,whencode) ->
+ let arity = all_same true tgt (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (declaration Ast0.NONE) whencode in
+ make_decl decl tgt arity (Ast0.Ddots(dots,whencode))
+ | Ast0.OptDecl(_) | Ast0.UniqueDecl(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Initializer *)
+
+and make_init =
+ make_opt_unique
+ (function x -> Ast0.OptIni x)
+ (function x -> Ast0.UniqueIni x)
+
+and initialiser tgt i =
+ let init_same = all_same true tgt in
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) ->
+ Ast0.rewrap i (Ast0.InitExpr(expression tgt exp))
+ | Ast0.InitList(lb,initlist,rb) ->
+ let arity = init_same (mcode2line lb) [mcode2arity lb; mcode2arity rb] in
+ let lb = mcode lb in
+ let initlist = dots (initialiser arity) initlist in
+ let rb = mcode rb in
+ make_init i tgt arity (Ast0.InitList(lb,initlist,rb))
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ let arity =
+ init_same (mcode2line dot) [mcode2arity dot; mcode2arity eq] in
+ let dot = mcode dot in
+ let name = ident true arity name in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity (Ast0.InitGccDotName(dot,name,eq,ini))
+ | Ast0.InitGccName(name,eq,ini) ->
+ let arity = init_same (mcode2line eq) [mcode2arity eq] in
+ let name = ident true arity name in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity (Ast0.InitGccName(name,eq,ini))
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ let arity =
+ init_same (mcode2line lb)
+ [mcode2arity lb; mcode2arity rb; mcode2arity eq] in
+ let lb = mcode lb in
+ let exp = expression arity exp in
+ let rb = mcode rb in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity (Ast0.InitGccIndex(lb,exp,rb,eq,ini))
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ let arity =
+ init_same (mcode2line lb)
+ [mcode2arity lb; mcode2arity dots; mcode2arity rb; mcode2arity eq] in
+ let lb = mcode lb in
+ let exp1 = expression arity exp1 in
+ let dots = mcode dots in
+ let exp2 = expression arity exp2 in
+ let rb = mcode rb in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity
+ (Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini))
+ | Ast0.IComma(cm) ->
+ let arity = init_same (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_init i tgt arity (Ast0.IComma(cm))
+ | Ast0.Idots(dots,whencode) ->
+ let arity = init_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (initialiser Ast0.NONE) whencode in
+ make_init i tgt arity (Ast0.Idots(dots,whencode))
+ | Ast0.OptIni(_) | Ast0.UniqueIni(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and make_param =
+ make_opt_unique
+ (function x -> Ast0.OptParam x)
+ (function x -> Ast0.UniqueParam x)
+
+and parameterTypeDef tgt param =
+ let param_same = all_same true tgt in
+ match Ast0.unwrap param with
+ Ast0.VoidParam(ty) -> Ast0.rewrap param (Ast0.VoidParam(typeC tgt ty))
+ | Ast0.Param(ty,Some id) ->
+ let ty = top_typeC tgt true ty in
+ let id = ident true tgt id in
+ Ast0.rewrap param
+ (match (Ast0.unwrap ty,Ast0.unwrap id) with
+ (Ast0.OptType(ty),Ast0.OptIdent(id)) ->
+ Ast0.OptParam(Ast0.rewrap param (Ast0.Param(ty,Some id)))
+ | (Ast0.UniqueType(ty),Ast0.UniqueIdent(id)) ->
+ Ast0.UniqueParam(Ast0.rewrap param (Ast0.Param(ty,Some id)))
+ | (Ast0.OptType(ty),_) ->
+ fail param "arity mismatch in param declaration"
+ | (_,Ast0.OptIdent(id)) ->
+ fail param "arity mismatch in param declaration"
+ | _ -> Ast0.Param(ty,Some id))
+ | Ast0.Param(ty,None) ->
+ let ty = top_typeC tgt true ty in
+ Ast0.rewrap param
+ (match Ast0.unwrap ty with
+ Ast0.OptType(ty) ->
+ Ast0.OptParam(Ast0.rewrap param (Ast0.Param(ty,None)))
+ | Ast0.UniqueType(ty) ->
+ Ast0.UniqueParam(Ast0.rewrap param (Ast0.Param(ty,None)))
+ | _ -> Ast0.Param(ty,None))
+ | Ast0.MetaParam(name,pure) ->
+ let arity = param_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_param param tgt arity (Ast0.MetaParam(name,pure))
+ | Ast0.MetaParamList(name,lenname,pure) ->
+ let arity = param_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_param param tgt arity (Ast0.MetaParamList(name,lenname,pure))
+ | Ast0.PComma(cm) ->
+ let arity = param_same (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_param param tgt arity (Ast0.PComma(cm))
+ | Ast0.Pdots(dots) ->
+ let arity = param_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ make_param param tgt arity (Ast0.Pdots(dots))
+ | Ast0.Pcircles(dots) ->
+ let arity = param_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ make_param param tgt arity (Ast0.Pcircles(dots))
+ | Ast0.OptParam(_) | Ast0.UniqueParam(_) ->
+ failwith "unexpected code"
+
+and parameter_list tgt = dots (parameterTypeDef tgt)
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and make_rule_elem x =
+ make_opt_unique
+ (function x -> Ast0.OptStm x)
+ (function x -> Ast0.UniqueStm x)
+ x
+
+and statement tgt stm =
+ let stm_same = all_same true tgt in
+ match Ast0.unwrap stm with
+ Ast0.Decl(bef,decl) ->
+ let new_decl = declaration tgt decl in
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_decl with
+ Ast0.OptDecl(decl) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.Decl(bef,decl)))
+ | Ast0.UniqueDecl(decl) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Decl(bef,decl)))
+ | _ -> Ast0.Decl(bef,new_decl))
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ let arity =
+ stm_same (mcode2line lbrace)
+ [mcode2arity lbrace; mcode2arity rbrace] in
+ let lbrace = mcode lbrace in
+ let body = dots (statement arity) body in
+ let rbrace = mcode rbrace in
+ make_rule_elem stm tgt arity (Ast0.Seq(lbrace,body,rbrace))
+ | Ast0.ExprStatement(exp,sem) ->
+ let arity = stm_same (mcode2line sem) [mcode2arity sem] in
+ let exp = expression arity exp in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.ExprStatement(exp,sem))
+ | Ast0.IfThen(iff,lp,exp,rp,branch,aft) ->
+ let arity =
+ stm_same (mcode2line iff) (List.map mcode2arity [iff;lp;rp]) in
+ let iff = mcode iff in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let branch = statement arity branch in
+ make_rule_elem stm tgt arity (Ast0.IfThen(iff,lp,exp,rp,branch,aft))
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
+ let arity =
+ stm_same (mcode2line iff) (List.map mcode2arity [iff;lp;rp;els]) in
+ let iff = mcode iff in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let branch1 = statement arity branch1 in
+ let els = mcode els in
+ let branch2 = statement arity branch2 in
+ make_rule_elem stm tgt arity
+ (Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft))
+ | Ast0.While(wh,lp,exp,rp,body,aft) ->
+ let arity =
+ stm_same (mcode2line wh)
+ (List.map mcode2arity [wh;lp;rp]) in
+ let wh = mcode wh in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let body = statement arity body in
+ make_rule_elem stm tgt arity (Ast0.While(wh,lp,exp,rp,body,aft))
+ | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
+ let arity =
+ stm_same (mcode2line wh) (List.map mcode2arity [d;wh;lp;rp;sem]) in
+ let d = mcode d in
+ let body = statement arity body in
+ let wh = mcode wh in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Do(d,body,wh,lp,exp,rp,sem))
+ | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,aft) ->
+ let arity =
+ stm_same (mcode2line fr) (List.map mcode2arity [fr;lp;sem1;sem2;rp]) in
+ let fr = mcode fr in
+ let lp = mcode lp in
+ let exp1 = get_option (expression arity) exp1 in
+ let sem1 = mcode sem1 in
+ let exp2 = get_option (expression arity) exp2 in
+ let sem2= mcode sem2 in
+ let exp3 = get_option (expression arity) exp3 in
+ let rp = mcode rp in
+ let body = statement arity body in
+ make_rule_elem stm tgt arity
+ (Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,aft))
+ | Ast0.Iterator(nm,lp,args,rp,body,aft) ->
+ let arity = stm_same (mcode2line lp) (List.map mcode2arity [lp;rp]) in
+ let nm = ident false arity nm in
+ let lp = mcode lp in
+ let args = dots (expression arity) args in
+ let rp = mcode rp in
+ let body = statement arity body in
+ make_rule_elem stm tgt arity (Ast0.Iterator(nm,lp,args,rp,body,aft))
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ let arity =
+ stm_same (mcode2line switch)
+ (List.map mcode2arity [switch;lp;rp;lb;rb]) in
+ let switch = mcode switch in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let lb = mcode lb in
+ let cases = dots (case_line arity) cases in
+ let rb = mcode rb in
+ make_rule_elem stm tgt arity
+ (Ast0.Switch(switch,lp,exp,rp,lb,cases,rb))
+ | Ast0.Break(br,sem) ->
+ let arity = stm_same (mcode2line br) (List.map mcode2arity [br;sem]) in
+ let br = mcode br in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Break(br,sem))
+ | Ast0.Continue(cont,sem) ->
+ let arity =
+ stm_same (mcode2line cont) (List.map mcode2arity [cont;sem]) in
+ let cont = mcode cont in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Continue(cont,sem))
+ | Ast0.Label(l,dd) ->
+ let arity = mcode2arity dd in
+ let l = ident false tgt l in
+ let dd = mcode dd in
+ make_rule_elem stm tgt arity (Ast0.Label(l,dd))
+ | Ast0.Goto(goto,l,sem) ->
+ let arity =
+ stm_same (mcode2line goto) (List.map mcode2arity [goto;sem]) in
+ let goto = mcode goto in
+ let l = ident false tgt l in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Goto(goto,l,sem))
+ | Ast0.Return(ret,sem) ->
+ let arity = stm_same (mcode2line ret) (List.map mcode2arity [ret;sem]) in
+ let ret = mcode ret in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Return(ret,sem))
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ let arity = stm_same (mcode2line ret) (List.map mcode2arity [ret;sem]) in
+ let ret = mcode ret in
+ let exp = expression arity exp in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.ReturnExpr(ret,exp,sem))
+ | Ast0.MetaStmt(name,pure) ->
+ let arity = stm_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_rule_elem stm tgt arity (Ast0.MetaStmt(name,pure))
+ | Ast0.MetaStmtList(name,pure) ->
+ let arity = stm_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_rule_elem stm tgt arity (Ast0.MetaStmtList(name,pure))
+ | Ast0.Exp(exp) ->
+ let new_exp = top_expression true tgt exp in
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_exp with
+ Ast0.OptExp(exp) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.Exp(exp)))
+ | Ast0.UniqueExp(exp) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Exp(exp)))
+ | _ -> Ast0.Exp(new_exp))
+ | Ast0.TopExp(exp) ->
+ let new_exp = top_expression true tgt exp in
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_exp with
+ Ast0.OptExp(exp) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.TopExp(exp)))
+ | Ast0.UniqueExp(exp) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.TopExp(exp)))
+ | _ -> Ast0.TopExp(new_exp))
+ | Ast0.Ty(ty) ->
+ let new_ty = typeC tgt ty in (* opt makes no sense alone at top level *)
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_ty with
+ Ast0.OptType(ty) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.Ty(ty)))
+ | Ast0.UniqueType(ty) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Ty(ty)))
+ | _ -> Ast0.Ty(new_ty))
+ | Ast0.Disj(starter,rule_elem_dots_list,mids,ender) ->
+ let stms =
+ List.map (function x -> concat_dots (statement tgt) x)
+ rule_elem_dots_list in
+ let (found_opt,unopt) =
+ List.fold_left
+ (function (found_opt,lines) ->
+ function x ->
+ let rebuild l =
+ (* previously just checked the last thing in the list,
+ but everything should be optional for the whole thing to
+ be optional *)
+ let is_opt x =
+ match Ast0.unwrap x with
+ Ast0.OptStm(x) -> true
+ | _ -> false in
+ let unopt x =
+ match Ast0.unwrap x with
+ Ast0.OptStm(x) -> x
+ | _ -> x in
+ if List.for_all is_opt l
+ then (true,List.map unopt l)
+ else (false, l) in
+ let (l,k) =
+ match Ast0.unwrap x with
+ Ast0.DOTS(l) ->
+ (l,function l -> Ast0.rewrap x (Ast0.DOTS l))
+ | Ast0.CIRCLES(l) ->
+ (l,function l -> Ast0.rewrap x (Ast0.CIRCLES l))
+ | Ast0.STARS(l) ->
+ (l,function l -> Ast0.rewrap x (Ast0.STARS l)) in
+ let (found_opt,l) = rebuild l in
+ (found_opt,(k l)::lines))
+ (false,[]) stms in
+ let unopt = List.rev unopt in
+ if found_opt
+ then
+ make_rule_elem stm tgt Ast0.OPT (Ast0.Disj(starter,unopt,mids,ender))
+ else Ast0.rewrap stm (Ast0.Disj(starter,stms,mids,ender))
+ | Ast0.Nest(starter,rule_elem_dots,ender,whn,multi) ->
+ let new_rule_elem_dots =
+ concat_dots (statement Ast0.NONE) rule_elem_dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ whn in
+ Ast0.rewrap stm
+ (Ast0.Nest(starter,new_rule_elem_dots,ender,whn,multi))
+ | Ast0.Dots(dots,whn) ->
+ let arity = stm_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ whn in
+ make_rule_elem stm tgt arity (Ast0.Dots(dots,whn))
+ | Ast0.Circles(dots,whn) ->
+ let arity = stm_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ whn in
+ make_rule_elem stm tgt arity (Ast0.Circles(dots,whn))
+ | Ast0.Stars(dots,whn) ->
+ let arity = stm_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ whn in
+ make_rule_elem stm tgt arity (Ast0.Stars(dots,whn))
+ | Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ let arity =
+ all_same true tgt (mcode2line lp)
+ ((List.map mcode2arity [lp;rp;lbrace;rbrace]) @ (fninfo2arity fi)) in
+ let fi = List.map (fninfo arity) fi in
+ let name = ident false arity name in
+ let lp = mcode lp in
+ let params = parameter_list arity params in
+ let rp = mcode rp in
+ let lbrace = mcode lbrace in
+ let body = dots (statement arity) body in
+ let rbrace = mcode rbrace in
+ make_rule_elem stm tgt arity
+ (Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace))
+ | Ast0.Include(inc,s) ->
+ let arity =
+ all_same true tgt (mcode2line inc) [mcode2arity inc; mcode2arity s] in
+ let inc = mcode inc in
+ let s = mcode s in
+ make_rule_elem stm tgt arity (Ast0.Include(inc,s))
+ | Ast0.Define(def,id,params,body) ->
+ let arity = all_same true tgt (mcode2line def) [mcode2arity def] in
+ let def = mcode def in
+ let id = ident false arity id in
+ let params = define_parameters arity params in
+ let body = dots (statement arity) body in
+ make_rule_elem stm tgt arity (Ast0.Define(def,id,params,body))
+ | Ast0.OptStm(_) | Ast0.UniqueStm(_) ->
+ failwith "unexpected code"
+
+and define_parameters tgt params =
+ match Ast0.unwrap params with
+ Ast0.NoParams -> params
+ | Ast0.DParams(lp,params,rp) ->
+ let arity =
+ all_same true tgt (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let lp = mcode lp in
+ let params = dots (define_param arity) params in
+ let rp = mcode rp in
+ Ast0.rewrap params (Ast0.DParams(lp,params,rp))
+
+and make_define_param x =
+ make_opt_unique
+ (function x -> Ast0.OptDParam x)
+ (function x -> Ast0.UniqueDParam x)
+ x
+
+and define_param tgt param =
+ match Ast0.unwrap param with
+ Ast0.DParam(id) ->
+ let new_id = ident true tgt id in
+ Ast0.rewrap param
+ (match Ast0.unwrap new_id with
+ Ast0.OptIdent(id) ->
+ Ast0.OptDParam(Ast0.rewrap param (Ast0.DParam(id)))
+ | Ast0.UniqueIdent(decl) ->
+ Ast0.UniqueDParam(Ast0.rewrap param (Ast0.DParam(id)))
+ | _ -> Ast0.DParam(new_id))
+ | Ast0.DPComma(cm) ->
+ let arity =
+ all_same true tgt (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_define_param param tgt arity (Ast0.DPComma(cm))
+ | Ast0.DPdots(dots) ->
+ let arity =
+ all_same true tgt (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ make_define_param param tgt arity (Ast0.DPdots(dots))
+ | Ast0.DPcircles(circles) ->
+ let arity =
+ all_same true tgt (mcode2line circles) [mcode2arity circles] in
+ let circles = mcode circles in
+ make_define_param param tgt arity (Ast0.DPcircles(circles))
+ | Ast0.OptDParam(dp) | Ast0.UniqueDParam(dp) ->
+ failwith "unexpected code"
+
+and fninfo arity = function
+ Ast0.FStorage(stg) -> Ast0.FStorage(mcode stg)
+ | Ast0.FType(ty) -> Ast0.FType(typeC arity ty)
+ | Ast0.FInline(inline) -> Ast0.FInline(mcode inline)
+ | Ast0.FAttr(attr) -> Ast0.FAttr(mcode attr)
+
+and fninfo2arity fninfo =
+ List.concat
+ (List.map
+ (function
+ Ast0.FStorage(stg) -> [mcode2arity stg]
+ | Ast0.FType(ty) -> []
+ | Ast0.FInline(inline) -> [mcode2arity inline]
+ | Ast0.FAttr(attr) -> [mcode2arity attr])
+ fninfo)
+
+and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> Ast0.WhenNot (notfn a)
+ | Ast0.WhenAlways a -> Ast0.WhenAlways (alwaysfn a)
+ | Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
+
+and make_case_line =
+ make_opt_unique
+ (function x -> Ast0.OptCase x)
+ (function x -> failwith "unique not allowed for case_line")
+
+and case_line tgt c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ let arity =
+ all_same true tgt (mcode2line def)
+ [mcode2arity def; mcode2arity colon] in
+ let def = mcode def in
+ let colon = mcode colon in
+ let code = dots (statement arity) code in
+ make_case_line c tgt arity (Ast0.Default(def,colon,code))
+ | Ast0.Case(case,exp,colon,code) ->
+ let arity =
+ all_same true tgt (mcode2line case)
+ [mcode2arity case; mcode2arity colon] in
+ let case = mcode case in
+ let exp = expression arity exp in
+ let colon = mcode colon in
+ let code = dots (statement arity) code in
+ make_case_line c tgt arity (Ast0.Case(case,exp,colon,code))
+ | Ast0.OptCase(_) -> failwith "unexpected OptCase"
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+(* Haven't thought much about arity here... *)
+
+let top_level tgt t =
+ Ast0.rewrap t
+ (match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ if mcode2arity old_file = Ast0.NONE && mcode2arity new_file = Ast0.NONE
+ then Ast0.FILEINFO(mcode old_file,mcode new_file)
+ else fail t "unexpected arity for file info"
+ | Ast0.DECL(stmt) ->
+ Ast0.DECL(statement tgt stmt)
+ | Ast0.CODE(rule_elem_dots) ->
+ Ast0.CODE(concat_dots (statement tgt) rule_elem_dots)
+ | Ast0.ERRORWORDS(exps) ->
+ Ast0.ERRORWORDS(List.map (top_expression false Ast0.NONE) exps)
+ | Ast0.OTHER(_) -> fail t "eliminated by top_level")
+
+let rule tgt = List.map (top_level tgt)
+
+(* --------------------------------------------------------------------- *)
+(* Entry points *)
+
+let minus_arity code =
+ rule Ast0.NONE code
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Arities matter for the minus slice, but not for the plus slice. *)
+
+(* ? only allowed on rule_elems, and on subterms if the context is ? also. *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+
+(* --------------------------------------------------------------------- *)
+
+let warning s = Printf.printf "warning: %s\n" s
+
+let fail w str =
+ failwith
+ (Printf.sprintf "cocci line %d: %s" ((Ast0.get_info w).Ast0.line_start)
+ str)
+
+let make_opt_unique optfn uniquefn info tgt arity term =
+ let term = Ast0.rewrap info term in
+ if tgt = arity
+ then term
+ else (* tgt must be NONE *)
+ match arity with
+ Ast0.OPT -> Ast0.copywrap info (optfn term)
+ | Ast0.UNIQUE -> Ast0.copywrap info (uniquefn term)
+ | Ast0.NONE -> failwith "tgt must be NONE"
+
+let all_same opt_allowed tgt line arities =
+ let tgt =
+ match tgt with
+ Ast0.NONE ->
+ (match List.hd arities with
+ Ast0.OPT when not opt_allowed ->
+ failwith "opt only allowed for the elements of a statement list"
+ | x -> x)
+ | _ -> tgt in
+ if not(List.for_all (function x -> x = tgt) arities)
+ then warning (Printf.sprintf "incompatible arity found on line %d" line);
+ tgt
+
+let get_option fn = function
+ None -> None
+ | Some x -> Some (fn x)
+
+let anyopt l fn = List.exists (function w -> fn(Ast0.unwrap w)) l
+
+let allopt l fn =
+ let rec loop = function
+ [] -> []
+ | x::xs ->
+ match fn (Ast0.unwrap x) with
+ Some x -> x :: (loop xs)
+ | None -> [] in
+ let res = loop l in
+ if List.length res = List.length l then Some res else None
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Mcode *)
+
+let mcode2line (_,_,info,_,_) = info.Ast0.line_start
+let mcode2arity (_,arity,_,_,_) = arity
+
+let mcode x = x (* nothing to do ... *)
+
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots fn d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) -> Ast0.DOTS(List.map fn x)
+ | Ast0.CIRCLES(x) -> Ast0.CIRCLES(List.map fn x)
+ | Ast0.STARS(x) -> Ast0.STARS(List.map fn x))
+
+let only_dots l =
+ not
+ (List.exists
+ (function x ->
+ match Ast0.unwrap x with
+ Ast0.Circles(_,_) | Ast0.Stars(_,_) -> true
+ | _ -> false)
+ l)
+
+let only_circles l =
+ not (List.exists
+ (function x ->
+ match Ast0.unwrap x with
+ Ast0.Dots(_,_) | Ast0.Stars(_,_) -> true
+ | _ -> false)
+ l)
+
+let only_stars l =
+ not (List.exists
+ (function x ->
+ match Ast0.unwrap x with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) -> true
+ | _ -> false)
+ l)
+
+let concat_dots fn d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) ->
+ let l = List.map fn x in
+ if only_dots l
+ then Ast0.DOTS(l)
+ else fail d "inconsistent dots usage"
+ | Ast0.CIRCLES(x) ->
+ let l = List.map fn x in
+ if only_circles l
+ then Ast0.CIRCLES(l)
+ else fail d "inconsistent dots usage"
+ | Ast0.STARS(x) ->
+ let l = List.map fn x in
+ if only_stars l
+ then Ast0.STARS(l)
+ else fail d "inconsistent dots usage")
+
+let flat_concat_dots fn d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> List.map fn x
+ | Ast0.CIRCLES(x) -> List.map fn x
+ | Ast0.STARS(x) -> List.map fn x
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let make_id =
+ make_opt_unique
+ (function x -> Ast0.OptIdent x)
+ (function x -> Ast0.UniqueIdent x)
+
+let ident opt_allowed tgt i =
+ match Ast0.unwrap i with
+ Ast0.Id(name) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.Id(name))
+ | Ast0.MetaId(name,constraints,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.MetaId(name,constraints,pure))
+ | Ast0.MetaFunc(name,constraints,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.MetaFunc(name,constraints,pure))
+ | Ast0.MetaLocalFunc(name,constraints,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name)
+ [mcode2arity name] in
+ let name = mcode name in
+ make_id i tgt arity (Ast0.MetaLocalFunc(name,constraints,pure))
+ | Ast0.OptIdent(_) | Ast0.UniqueIdent(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let make_exp =
+ make_opt_unique
+ (function x -> Ast0.OptExp x)
+ (function x -> Ast0.UniqueExp x)
+
+let rec top_expression opt_allowed tgt expr =
+ let exp_same = all_same opt_allowed tgt in
+ match Ast0.unwrap expr with
+ Ast0.Ident(id) ->
+ let new_id = ident opt_allowed tgt id in
+ Ast0.rewrap expr
+ (match Ast0.unwrap new_id with
+ Ast0.OptIdent(id) ->
+ Ast0.OptExp(Ast0.rewrap expr (Ast0.Ident(id)))
+ | Ast0.UniqueIdent(id) ->
+ Ast0.UniqueExp(Ast0.rewrap expr (Ast0.Ident(id)))
+ | _ -> Ast0.Ident(new_id))
+ | Ast0.Constant(const) ->
+ let arity = exp_same (mcode2line const) [mcode2arity const] in
+ let const = mcode const in
+ make_exp expr tgt arity (Ast0.Constant(const))
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let fn = expression arity fn in
+ let lp = mcode lp in
+ let args = dots (expression arity) args in
+ let rp = mcode rp in
+ make_exp expr tgt arity (Ast0.FunCall(fn,lp,args,rp))
+ | Ast0.Assignment(left,op,right,simple) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let left = expression arity left in
+ let op = mcode op in
+ let right = expression arity right in
+ make_exp expr tgt arity (Ast0.Assignment(left,op,right,simple))
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ let arity =
+ exp_same (mcode2line why) [mcode2arity why; mcode2arity colon] in
+ let exp1 = expression arity exp1 in
+ let why = mcode why in
+ let exp2 = get_option (expression arity) exp2 in
+ let colon = mcode colon in
+ let exp3 = expression arity exp3 in
+ make_exp expr tgt arity (Ast0.CondExpr(exp1,why,exp2,colon,exp3))
+ | Ast0.Postfix(exp,op) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let exp = expression arity exp in
+ let op = mcode op in
+ make_exp expr tgt arity (Ast0.Postfix(exp,op))
+ | Ast0.Infix(exp,op) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let exp = expression arity exp in
+ let op = mcode op in
+ make_exp expr tgt arity (Ast0.Infix(exp,op))
+ | Ast0.Unary(exp,op) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let exp = expression arity exp in
+ let op = mcode op in
+ make_exp expr tgt arity (Ast0.Unary(exp,op))
+ | Ast0.Binary(left,op,right) ->
+ let arity = exp_same (mcode2line op) [mcode2arity op] in
+ let left = expression arity left in
+ let op = mcode op in
+ let right = expression arity right in
+ make_exp expr tgt arity (Ast0.Binary(left,op,right))
+ | Ast0.Nested(left,op,right) -> failwith "nested in arity not possible"
+ | Ast0.Paren(lp,exp,rp) ->
+ let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ make_exp expr tgt arity (Ast0.Paren(lp,exp,rp))
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ let arity = exp_same (mcode2line lb) [mcode2arity lb; mcode2arity rb] in
+ let exp1 = expression arity exp1 in
+ let lb = mcode lb in
+ let exp2 = expression arity exp2 in
+ let rb = mcode rb in
+ make_exp expr tgt arity (Ast0.ArrayAccess(exp1,lb,exp2,rb))
+ | Ast0.RecordAccess(exp,pt,field) ->
+ let arity = exp_same (mcode2line pt) [mcode2arity pt] in
+ let exp = expression arity exp in
+ let pt = mcode pt in
+ let field = ident false arity field in
+ make_exp expr tgt arity (Ast0.RecordAccess(exp,pt,field))
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ let arity = exp_same (mcode2line ar) [mcode2arity ar] in
+ let exp = expression arity exp in
+ let ar = mcode ar in
+ let field = ident false arity field in
+ make_exp expr tgt arity (Ast0.RecordPtAccess(exp,ar,field))
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let lp = mcode lp in
+ let ty = typeC arity ty in
+ let rp = mcode rp in
+ let exp = expression arity exp in
+ make_exp expr tgt arity (Ast0.Cast(lp,ty,rp,exp))
+ | Ast0.SizeOfExpr(szf,exp) ->
+ let arity = exp_same (mcode2line szf) [mcode2arity szf] in
+ let szf = mcode szf in
+ let exp = expression arity exp in
+ make_exp expr tgt arity (Ast0.SizeOfExpr(szf,exp))
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ let arity =
+ exp_same (mcode2line szf) (List.map mcode2arity [szf;lp;rp]) in
+ let szf = mcode szf in
+ let lp = mcode lp in
+ let ty = typeC arity ty in
+ let rp = mcode rp in
+ make_exp expr tgt arity (Ast0.SizeOfType(szf,lp,ty,rp))
+ | Ast0.TypeExp(ty) -> Ast0.rewrap expr (Ast0.TypeExp(typeC tgt ty))
+ | Ast0.MetaErr(name,constraints,pure) ->
+ let arity = exp_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_exp expr tgt arity (Ast0.MetaErr(name,constraints,pure))
+ | Ast0.MetaExpr(name,constraints,ty,form,pure) ->
+ let arity = exp_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_exp expr tgt arity (Ast0.MetaExpr(name,constraints,ty,form,pure))
+ | Ast0.MetaExprList(name,lenname,pure) ->
+ let arity = exp_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_exp expr tgt arity (Ast0.MetaExprList(name,lenname,pure))
+ | Ast0.EComma(cm) ->
+ let arity = exp_same (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_exp expr tgt arity (Ast0.EComma(cm))
+ | Ast0.DisjExpr(starter,exps,mids,ender) ->
+ let exps = List.map (top_expression opt_allowed tgt) exps in
+ (match List.rev exps with
+ _::xs ->
+ if anyopt xs (function Ast0.OptExp(_) -> true | _ -> false)
+ then fail expr "opt only allowed in the last disjunct"
+ | _ -> ());
+ Ast0.rewrap expr (Ast0.DisjExpr(starter,exps,mids,ender))
+ | Ast0.NestExpr(starter,exp_dots,ender,whencode,multi) ->
+ let res =
+ Ast0.NestExpr(starter,
+ dots (top_expression true Ast0.NONE) exp_dots,
+ ender,whencode,multi) in
+ Ast0.rewrap expr res
+ | Ast0.Edots(dots,whencode) ->
+ let arity = exp_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (expression Ast0.NONE) whencode in
+ make_exp expr tgt arity (Ast0.Edots(dots,whencode))
+ | Ast0.Ecircles(dots,whencode) ->
+ let arity = exp_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (expression Ast0.NONE) whencode in
+ make_exp expr tgt arity (Ast0.Ecircles(dots,whencode))
+ | Ast0.Estars(dots,whencode) ->
+ let arity = exp_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (expression Ast0.NONE) whencode in
+ make_exp expr tgt arity (Ast0.Estars(dots,whencode))
+ | Ast0.OptExp(_) | Ast0.UniqueExp(_) ->
+ failwith "unexpected code"
+
+and expression tgt exp = top_expression false tgt exp
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and make_typeC =
+ make_opt_unique
+ (function x -> Ast0.OptType x)
+ (function x -> Ast0.UniqueType x)
+
+and top_typeC tgt opt_allowed typ =
+ match Ast0.unwrap typ with
+ Ast0.ConstVol(cv,ty) ->
+ let arity = all_same opt_allowed tgt (mcode2line cv)
+ [mcode2arity cv] in
+ let cv = mcode cv in
+ let ty = typeC arity ty in
+ make_typeC typ tgt arity (Ast0.ConstVol(cv,ty))
+ | Ast0.BaseType(ty,Some sign) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line ty)
+ [mcode2arity ty; mcode2arity sign] in
+ let ty = mcode ty in
+ let sign = mcode sign in
+ make_typeC typ tgt arity (Ast0.BaseType(ty,Some sign))
+ | Ast0.BaseType(ty,None) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line ty) [mcode2arity ty] in
+ let ty = mcode ty in
+ make_typeC typ tgt arity (Ast0.BaseType(ty,None))
+ | Ast0.ImplicitInt(sign) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line sign) [mcode2arity sign] in
+ let sign = mcode sign in
+ make_typeC typ tgt arity (Ast0.ImplicitInt(sign))
+ | Ast0.Pointer(ty,star) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line star) [mcode2arity star] in
+ let ty = typeC arity ty in
+ let star = mcode star in
+ make_typeC typ tgt arity (Ast0.Pointer(ty,star))
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lp1)
+ (List.map mcode2arity [lp1;star;rp1;lp2;rp2]) in
+ let ty = typeC arity ty in
+ let params = parameter_list tgt params in
+ make_typeC typ tgt arity
+ (Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2))
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lp1)
+ (List.map mcode2arity [lp1;rp1]) in
+ let ty = get_option (typeC arity) ty in
+ let params = parameter_list tgt params in
+ make_typeC typ tgt arity (Ast0.FunctionType(ty,lp1,params,rp1))
+ | Ast0.Array(ty,lb,size,rb) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lb)
+ [mcode2arity lb;mcode2arity rb] in
+ let ty = typeC arity ty in
+ let lb = mcode lb in
+ let size = get_option (expression arity) size in
+ let rb = mcode rb in
+ make_typeC typ tgt arity (Ast0.Array(ty,lb,size,rb))
+ | Ast0.StructUnionName(kind,name) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line kind)
+ [mcode2arity kind] in
+ let kind = mcode kind in
+ let name = get_option (ident false arity) name in
+ make_typeC typ tgt arity (Ast0.StructUnionName(kind,name))
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line lb)
+ (List.map mcode2arity [lb;rb]) in
+ let ty = typeC arity ty in
+ let lb = mcode lb in
+ let decls = dots (declaration tgt) decls in
+ let rb = mcode rb in
+ make_typeC typ tgt arity (Ast0.StructUnionDef(ty,lb,decls,rb))
+ | Ast0.TypeName(name) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_typeC typ tgt arity (Ast0.TypeName(name))
+ | Ast0.MetaType(name,pure) ->
+ let arity =
+ all_same opt_allowed tgt (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_typeC typ tgt arity (Ast0.MetaType(name,pure))
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ let types = List.map (typeC tgt) types in
+ (match List.rev types with
+ _::xs ->
+ if anyopt xs (function Ast0.OptType(_) -> true | _ -> false)
+ then fail typ "opt only allowed in the last disjunct"
+ | _ -> ());
+ let res = Ast0.DisjType(starter,types,mids,ender) in
+ Ast0.rewrap typ res
+ | Ast0.OptType(_) | Ast0.UniqueType(_) ->
+ failwith "unexpected code"
+
+and typeC tgt ty = top_typeC tgt false ty
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and make_decl =
+ make_opt_unique
+ (function x -> Ast0.OptDecl x)
+ (function x -> Ast0.UniqueDecl x)
+
+and declaration tgt decl =
+ match Ast0.unwrap decl with
+ Ast0.Init(stg,ty,id,eq,exp,sem) ->
+ let arity =
+ all_same true tgt (mcode2line eq)
+ ((match stg with None -> [] | Some x -> [mcode2arity x]) @
+ (List.map mcode2arity [eq;sem])) in
+ let stg = get_option mcode stg in
+ let ty = typeC arity ty in
+ let id = ident false arity id in
+ let eq = mcode eq in
+ let exp = initialiser arity exp in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.Init(stg,ty,id,eq,exp,sem))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ let arity =
+ all_same true tgt (mcode2line sem)
+ ((match stg with None -> [] | Some x -> [mcode2arity x]) @
+ [mcode2arity sem]) in
+ let stg = get_option mcode stg in
+ let ty = typeC arity ty in
+ let id = ident false arity id in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.UnInit(stg,ty,id,sem))
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ let arity =
+ all_same true tgt (mcode2line lp) (List.map mcode2arity [lp;rp;sem]) in
+ let name = ident false arity name in
+ let lp = mcode lp in
+ let args = dots (expression arity) args in
+ let rp = mcode rp in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.MacroDecl(name,lp,args,rp,sem))
+ | Ast0.TyDecl(ty,sem) ->
+ let arity =
+ all_same true tgt (mcode2line sem) [mcode2arity sem] in
+ let ty = typeC arity ty in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.TyDecl(ty,sem))
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ let arity =
+ all_same true tgt (mcode2line sem)
+ [mcode2arity stg;mcode2arity sem] in
+ let stg = mcode stg in
+ let ty = typeC arity ty in
+ let id = typeC arity id in
+ let sem = mcode sem in
+ make_decl decl tgt arity (Ast0.Typedef(stg,ty,id,sem))
+ | Ast0.DisjDecl(starter,decls,mids,ender) ->
+ let decls = List.map (declaration tgt) decls in
+ (match List.rev decls with
+ _::xs ->
+ if anyopt xs (function Ast0.OptDecl(_) -> true | _ -> false)
+ then fail decl "opt only allowed in the last disjunct"
+ | _ -> ());
+ let res = Ast0.DisjDecl(starter,decls,mids,ender) in
+ Ast0.rewrap decl res
+ | Ast0.Ddots(dots,whencode) ->
+ let arity = all_same true tgt (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (declaration Ast0.NONE) whencode in
+ make_decl decl tgt arity (Ast0.Ddots(dots,whencode))
+ | Ast0.OptDecl(_) | Ast0.UniqueDecl(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Initializer *)
+
+and make_init =
+ make_opt_unique
+ (function x -> Ast0.OptIni x)
+ (function x -> Ast0.UniqueIni x)
+
+and initialiser tgt i =
+ let init_same = all_same true tgt in
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) ->
+ Ast0.rewrap i (Ast0.InitExpr(expression tgt exp))
+ | Ast0.InitList(lb,initlist,rb) ->
+ let arity = init_same (mcode2line lb) [mcode2arity lb; mcode2arity rb] in
+ let lb = mcode lb in
+ let initlist = dots (initialiser arity) initlist in
+ let rb = mcode rb in
+ make_init i tgt arity (Ast0.InitList(lb,initlist,rb))
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ let arity =
+ init_same (mcode2line dot) [mcode2arity dot; mcode2arity eq] in
+ let dot = mcode dot in
+ let name = ident true arity name in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity (Ast0.InitGccDotName(dot,name,eq,ini))
+ | Ast0.InitGccName(name,eq,ini) ->
+ let arity = init_same (mcode2line eq) [mcode2arity eq] in
+ let name = ident true arity name in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity (Ast0.InitGccName(name,eq,ini))
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ let arity =
+ init_same (mcode2line lb)
+ [mcode2arity lb; mcode2arity rb; mcode2arity eq] in
+ let lb = mcode lb in
+ let exp = expression arity exp in
+ let rb = mcode rb in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity (Ast0.InitGccIndex(lb,exp,rb,eq,ini))
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ let arity =
+ init_same (mcode2line lb)
+ [mcode2arity lb; mcode2arity dots; mcode2arity rb; mcode2arity eq] in
+ let lb = mcode lb in
+ let exp1 = expression arity exp1 in
+ let dots = mcode dots in
+ let exp2 = expression arity exp2 in
+ let rb = mcode rb in
+ let eq = mcode eq in
+ let ini = initialiser arity ini in
+ make_init i tgt arity
+ (Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini))
+ | Ast0.IComma(cm) ->
+ let arity = init_same (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_init i tgt arity (Ast0.IComma(cm))
+ | Ast0.Idots(dots,whencode) ->
+ let arity = init_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whencode = get_option (initialiser Ast0.NONE) whencode in
+ make_init i tgt arity (Ast0.Idots(dots,whencode))
+ | Ast0.OptIni(_) | Ast0.UniqueIni(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and make_param =
+ make_opt_unique
+ (function x -> Ast0.OptParam x)
+ (function x -> Ast0.UniqueParam x)
+
+and parameterTypeDef tgt param =
+ let param_same = all_same true tgt in
+ match Ast0.unwrap param with
+ Ast0.VoidParam(ty) -> Ast0.rewrap param (Ast0.VoidParam(typeC tgt ty))
+ | Ast0.Param(ty,Some id) ->
+ let ty = top_typeC tgt true ty in
+ let id = ident true tgt id in
+ Ast0.rewrap param
+ (match (Ast0.unwrap ty,Ast0.unwrap id) with
+ (Ast0.OptType(ty),Ast0.OptIdent(id)) ->
+ Ast0.OptParam(Ast0.rewrap param (Ast0.Param(ty,Some id)))
+ | (Ast0.UniqueType(ty),Ast0.UniqueIdent(id)) ->
+ Ast0.UniqueParam(Ast0.rewrap param (Ast0.Param(ty,Some id)))
+ | (Ast0.OptType(ty),_) ->
+ fail param "arity mismatch in param declaration"
+ | (_,Ast0.OptIdent(id)) ->
+ fail param "arity mismatch in param declaration"
+ | _ -> Ast0.Param(ty,Some id))
+ | Ast0.Param(ty,None) ->
+ let ty = top_typeC tgt true ty in
+ Ast0.rewrap param
+ (match Ast0.unwrap ty with
+ Ast0.OptType(ty) ->
+ Ast0.OptParam(Ast0.rewrap param (Ast0.Param(ty,None)))
+ | Ast0.UniqueType(ty) ->
+ Ast0.UniqueParam(Ast0.rewrap param (Ast0.Param(ty,None)))
+ | _ -> Ast0.Param(ty,None))
+ | Ast0.MetaParam(name,pure) ->
+ let arity = param_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_param param tgt arity (Ast0.MetaParam(name,pure))
+ | Ast0.MetaParamList(name,lenname,pure) ->
+ let arity = param_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_param param tgt arity (Ast0.MetaParamList(name,lenname,pure))
+ | Ast0.PComma(cm) ->
+ let arity = param_same (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_param param tgt arity (Ast0.PComma(cm))
+ | Ast0.Pdots(dots) ->
+ let arity = param_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ make_param param tgt arity (Ast0.Pdots(dots))
+ | Ast0.Pcircles(dots) ->
+ let arity = param_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ make_param param tgt arity (Ast0.Pcircles(dots))
+ | Ast0.OptParam(_) | Ast0.UniqueParam(_) ->
+ failwith "unexpected code"
+
+and parameter_list tgt = dots (parameterTypeDef tgt)
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and make_rule_elem x =
+ make_opt_unique
+ (function x -> Ast0.OptStm x)
+ (function x -> Ast0.UniqueStm x)
+ x
+
+and statement tgt stm =
+ let stm_same = all_same true tgt in
+ match Ast0.unwrap stm with
+ Ast0.Decl(bef,decl) ->
+ let new_decl = declaration tgt decl in
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_decl with
+ Ast0.OptDecl(decl) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.Decl(bef,decl)))
+ | Ast0.UniqueDecl(decl) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Decl(bef,decl)))
+ | _ -> Ast0.Decl(bef,new_decl))
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ let arity =
+ stm_same (mcode2line lbrace)
+ [mcode2arity lbrace; mcode2arity rbrace] in
+ let lbrace = mcode lbrace in
+ let body = dots (statement arity) body in
+ let rbrace = mcode rbrace in
+ make_rule_elem stm tgt arity (Ast0.Seq(lbrace,body,rbrace))
+ | Ast0.ExprStatement(exp,sem) ->
+ let arity = stm_same (mcode2line sem) [mcode2arity sem] in
+ let exp = expression arity exp in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.ExprStatement(exp,sem))
+ | Ast0.IfThen(iff,lp,exp,rp,branch,aft) ->
+ let arity =
+ stm_same (mcode2line iff) (List.map mcode2arity [iff;lp;rp]) in
+ let iff = mcode iff in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let branch = statement arity branch in
+ make_rule_elem stm tgt arity (Ast0.IfThen(iff,lp,exp,rp,branch,aft))
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
+ let arity =
+ stm_same (mcode2line iff) (List.map mcode2arity [iff;lp;rp;els]) in
+ let iff = mcode iff in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let branch1 = statement arity branch1 in
+ let els = mcode els in
+ let branch2 = statement arity branch2 in
+ make_rule_elem stm tgt arity
+ (Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft))
+ | Ast0.While(wh,lp,exp,rp,body,aft) ->
+ let arity =
+ stm_same (mcode2line wh)
+ (List.map mcode2arity [wh;lp;rp]) in
+ let wh = mcode wh in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let body = statement arity body in
+ make_rule_elem stm tgt arity (Ast0.While(wh,lp,exp,rp,body,aft))
+ | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
+ let arity =
+ stm_same (mcode2line wh) (List.map mcode2arity [d;wh;lp;rp;sem]) in
+ let d = mcode d in
+ let body = statement arity body in
+ let wh = mcode wh in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Do(d,body,wh,lp,exp,rp,sem))
+ | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,aft) ->
+ let arity =
+ stm_same (mcode2line fr) (List.map mcode2arity [fr;lp;sem1;sem2;rp]) in
+ let fr = mcode fr in
+ let lp = mcode lp in
+ let exp1 = get_option (expression arity) exp1 in
+ let sem1 = mcode sem1 in
+ let exp2 = get_option (expression arity) exp2 in
+ let sem2= mcode sem2 in
+ let exp3 = get_option (expression arity) exp3 in
+ let rp = mcode rp in
+ let body = statement arity body in
+ make_rule_elem stm tgt arity
+ (Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,aft))
+ | Ast0.Iterator(nm,lp,args,rp,body,aft) ->
+ let arity = stm_same (mcode2line lp) (List.map mcode2arity [lp;rp]) in
+ let nm = ident false arity nm in
+ let lp = mcode lp in
+ let args = dots (expression arity) args in
+ let rp = mcode rp in
+ let body = statement arity body in
+ make_rule_elem stm tgt arity (Ast0.Iterator(nm,lp,args,rp,body,aft))
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ let arity =
+ stm_same (mcode2line switch)
+ (List.map mcode2arity [switch;lp;rp;lb;rb]) in
+ let switch = mcode switch in
+ let lp = mcode lp in
+ let exp = expression arity exp in
+ let rp = mcode rp in
+ let lb = mcode lb in
+ let cases = dots (case_line arity) cases in
+ let rb = mcode rb in
+ make_rule_elem stm tgt arity
+ (Ast0.Switch(switch,lp,exp,rp,lb,cases,rb))
+ | Ast0.Break(br,sem) ->
+ let arity = stm_same (mcode2line br) (List.map mcode2arity [br;sem]) in
+ let br = mcode br in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Break(br,sem))
+ | Ast0.Continue(cont,sem) ->
+ let arity =
+ stm_same (mcode2line cont) (List.map mcode2arity [cont;sem]) in
+ let cont = mcode cont in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Continue(cont,sem))
+ | Ast0.Label(l,dd) ->
+ let arity = mcode2arity dd in
+ let l = ident false tgt l in
+ let dd = mcode dd in
+ make_rule_elem stm tgt arity (Ast0.Label(l,dd))
+ | Ast0.Goto(goto,l,sem) ->
+ let arity =
+ stm_same (mcode2line goto) (List.map mcode2arity [goto;sem]) in
+ let goto = mcode goto in
+ let l = ident false tgt l in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Goto(goto,l,sem))
+ | Ast0.Return(ret,sem) ->
+ let arity = stm_same (mcode2line ret) (List.map mcode2arity [ret;sem]) in
+ let ret = mcode ret in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.Return(ret,sem))
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ let arity = stm_same (mcode2line ret) (List.map mcode2arity [ret;sem]) in
+ let ret = mcode ret in
+ let exp = expression arity exp in
+ let sem = mcode sem in
+ make_rule_elem stm tgt arity (Ast0.ReturnExpr(ret,exp,sem))
+ | Ast0.MetaStmt(name,pure) ->
+ let arity = stm_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_rule_elem stm tgt arity (Ast0.MetaStmt(name,pure))
+ | Ast0.MetaStmtList(name,pure) ->
+ let arity = stm_same (mcode2line name) [mcode2arity name] in
+ let name = mcode name in
+ make_rule_elem stm tgt arity (Ast0.MetaStmtList(name,pure))
+ | Ast0.Exp(exp) ->
+ let new_exp = top_expression true tgt exp in
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_exp with
+ Ast0.OptExp(exp) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.Exp(exp)))
+ | Ast0.UniqueExp(exp) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Exp(exp)))
+ | _ -> Ast0.Exp(new_exp))
+ | Ast0.TopExp(exp) ->
+ let new_exp = top_expression true tgt exp in
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_exp with
+ Ast0.OptExp(exp) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.TopExp(exp)))
+ | Ast0.UniqueExp(exp) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.TopExp(exp)))
+ | _ -> Ast0.TopExp(new_exp))
+ | Ast0.Ty(ty) ->
+ let new_ty = typeC tgt ty in (* opt makes no sense alone at top level *)
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_ty with
+ Ast0.OptType(ty) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.Ty(ty)))
+ | Ast0.UniqueType(ty) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Ty(ty)))
+ | _ -> Ast0.Ty(new_ty))
+ | Ast0.Disj(starter,rule_elem_dots_list,mids,ender) ->
+ let stms =
+ List.map (function x -> concat_dots (statement tgt) x)
+ rule_elem_dots_list in
+ let (found_opt,unopt) =
+ List.fold_left
+ (function (found_opt,lines) ->
+ function x ->
+ let rebuild l =
+ (* previously just checked the last thing in the list,
+ but everything should be optional for the whole thing to
+ be optional *)
+ let is_opt x =
+ match Ast0.unwrap x with
+ Ast0.OptStm(x) -> true
+ | _ -> false in
+ let unopt x =
+ match Ast0.unwrap x with
+ Ast0.OptStm(x) -> x
+ | _ -> x in
+ if List.for_all is_opt l
+ then (true,List.map unopt l)
+ else (false, l) in
+ let (l,k) =
+ match Ast0.unwrap x with
+ Ast0.DOTS(l) ->
+ (l,function l -> Ast0.rewrap x (Ast0.DOTS l))
+ | Ast0.CIRCLES(l) ->
+ (l,function l -> Ast0.rewrap x (Ast0.CIRCLES l))
+ | Ast0.STARS(l) ->
+ (l,function l -> Ast0.rewrap x (Ast0.STARS l)) in
+ let (found_opt,l) = rebuild l in
+ (found_opt,(k l)::lines))
+ (false,[]) stms in
+ let unopt = List.rev unopt in
+ if found_opt
+ then
+ make_rule_elem stm tgt Ast0.OPT (Ast0.Disj(starter,unopt,mids,ender))
+ else Ast0.rewrap stm (Ast0.Disj(starter,stms,mids,ender))
+ | Ast0.Nest(starter,rule_elem_dots,ender,whn,multi) ->
+ let new_rule_elem_dots =
+ concat_dots (statement Ast0.NONE) rule_elem_dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
+ whn in
+ Ast0.rewrap stm
+ (Ast0.Nest(starter,new_rule_elem_dots,ender,whn,multi))
+ | Ast0.Dots(dots,whn) ->
+ let arity = stm_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
+ whn in
+ make_rule_elem stm tgt arity (Ast0.Dots(dots,whn))
+ | Ast0.Circles(dots,whn) ->
+ let arity = stm_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
+ whn in
+ make_rule_elem stm tgt arity (Ast0.Circles(dots,whn))
+ | Ast0.Stars(dots,whn) ->
+ let arity = stm_same (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ let whn =
+ List.map
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
+ whn in
+ make_rule_elem stm tgt arity (Ast0.Stars(dots,whn))
+ | Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ let arity =
+ all_same true tgt (mcode2line lp)
+ ((List.map mcode2arity [lp;rp;lbrace;rbrace]) @ (fninfo2arity fi)) in
+ let fi = List.map (fninfo arity) fi in
+ let name = ident false arity name in
+ let lp = mcode lp in
+ let params = parameter_list arity params in
+ let rp = mcode rp in
+ let lbrace = mcode lbrace in
+ let body = dots (statement arity) body in
+ let rbrace = mcode rbrace in
+ make_rule_elem stm tgt arity
+ (Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace))
+ | Ast0.Include(inc,s) ->
+ let arity =
+ all_same true tgt (mcode2line inc) [mcode2arity inc; mcode2arity s] in
+ let inc = mcode inc in
+ let s = mcode s in
+ make_rule_elem stm tgt arity (Ast0.Include(inc,s))
+ | Ast0.Define(def,id,params,body) ->
+ let arity = all_same true tgt (mcode2line def) [mcode2arity def] in
+ let def = mcode def in
+ let id = ident false arity id in
+ let params = define_parameters arity params in
+ let body = dots (statement arity) body in
+ make_rule_elem stm tgt arity (Ast0.Define(def,id,params,body))
+ | Ast0.OptStm(_) | Ast0.UniqueStm(_) ->
+ failwith "unexpected code"
+
+and define_parameters tgt params =
+ match Ast0.unwrap params with
+ Ast0.NoParams -> params
+ | Ast0.DParams(lp,params,rp) ->
+ let arity =
+ all_same true tgt (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
+ let lp = mcode lp in
+ let params = dots (define_param arity) params in
+ let rp = mcode rp in
+ Ast0.rewrap params (Ast0.DParams(lp,params,rp))
+
+and make_define_param x =
+ make_opt_unique
+ (function x -> Ast0.OptDParam x)
+ (function x -> Ast0.UniqueDParam x)
+ x
+
+and define_param tgt param =
+ match Ast0.unwrap param with
+ Ast0.DParam(id) ->
+ let new_id = ident true tgt id in
+ Ast0.rewrap param
+ (match Ast0.unwrap new_id with
+ Ast0.OptIdent(id) ->
+ Ast0.OptDParam(Ast0.rewrap param (Ast0.DParam(id)))
+ | Ast0.UniqueIdent(decl) ->
+ Ast0.UniqueDParam(Ast0.rewrap param (Ast0.DParam(id)))
+ | _ -> Ast0.DParam(new_id))
+ | Ast0.DPComma(cm) ->
+ let arity =
+ all_same true tgt (mcode2line cm) [mcode2arity cm] in
+ let cm = mcode cm in
+ make_define_param param tgt arity (Ast0.DPComma(cm))
+ | Ast0.DPdots(dots) ->
+ let arity =
+ all_same true tgt (mcode2line dots) [mcode2arity dots] in
+ let dots = mcode dots in
+ make_define_param param tgt arity (Ast0.DPdots(dots))
+ | Ast0.DPcircles(circles) ->
+ let arity =
+ all_same true tgt (mcode2line circles) [mcode2arity circles] in
+ let circles = mcode circles in
+ make_define_param param tgt arity (Ast0.DPcircles(circles))
+ | Ast0.OptDParam(dp) | Ast0.UniqueDParam(dp) ->
+ failwith "unexpected code"
+
+and fninfo arity = function
+ Ast0.FStorage(stg) -> Ast0.FStorage(mcode stg)
+ | Ast0.FType(ty) -> Ast0.FType(typeC arity ty)
+ | Ast0.FInline(inline) -> Ast0.FInline(mcode inline)
+ | Ast0.FAttr(attr) -> Ast0.FAttr(mcode attr)
+
+and fninfo2arity fninfo =
+ List.concat
+ (List.map
+ (function
+ Ast0.FStorage(stg) -> [mcode2arity stg]
+ | Ast0.FType(ty) -> []
+ | Ast0.FInline(inline) -> [mcode2arity inline]
+ | Ast0.FAttr(attr) -> [mcode2arity attr])
+ fninfo)
+
+and whencode notfn alwaysfn expression = function
+ Ast0.WhenNot a -> Ast0.WhenNot (notfn a)
+ | Ast0.WhenAlways a -> Ast0.WhenAlways (alwaysfn a)
+ | Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
+ | Ast0.WhenNotTrue a -> Ast0.WhenNotTrue (expression a)
+ | Ast0.WhenNotFalse a -> Ast0.WhenNotFalse (expression a)
+
+and make_case_line =
+ make_opt_unique
+ (function x -> Ast0.OptCase x)
+ (function x -> failwith "unique not allowed for case_line")
+
+and case_line tgt c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ let arity =
+ all_same true tgt (mcode2line def)
+ [mcode2arity def; mcode2arity colon] in
+ let def = mcode def in
+ let colon = mcode colon in
+ let code = dots (statement arity) code in
+ make_case_line c tgt arity (Ast0.Default(def,colon,code))
+ | Ast0.Case(case,exp,colon,code) ->
+ let arity =
+ all_same true tgt (mcode2line case)
+ [mcode2arity case; mcode2arity colon] in
+ let case = mcode case in
+ let exp = expression arity exp in
+ let colon = mcode colon in
+ let code = dots (statement arity) code in
+ make_case_line c tgt arity (Ast0.Case(case,exp,colon,code))
+ | Ast0.OptCase(_) -> failwith "unexpected OptCase"
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+(* Haven't thought much about arity here... *)
+
+let top_level tgt t =
+ Ast0.rewrap t
+ (match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ if mcode2arity old_file = Ast0.NONE && mcode2arity new_file = Ast0.NONE
+ then Ast0.FILEINFO(mcode old_file,mcode new_file)
+ else fail t "unexpected arity for file info"
+ | Ast0.DECL(stmt) ->
+ Ast0.DECL(statement tgt stmt)
+ | Ast0.CODE(rule_elem_dots) ->
+ Ast0.CODE(concat_dots (statement tgt) rule_elem_dots)
+ | Ast0.ERRORWORDS(exps) ->
+ Ast0.ERRORWORDS(List.map (top_expression false Ast0.NONE) exps)
+ | Ast0.OTHER(_) -> fail t "eliminated by top_level")
+
+let rule tgt = List.map (top_level tgt)
+
+(* --------------------------------------------------------------------- *)
+(* Entry points *)
+
+let minus_arity code =
+ rule Ast0.NONE code
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+type arity = OPT | UNIQUE | NONE
+
+type token_info =
+ { tline_start : int; tline_end : int;
+ left_offset : int; right_offset : int }
+let default_token_info =
+ { tline_start = -1; tline_end = -1; left_offset = -1; right_offset = -1 }
+
+(* MIXED is like CONTEXT, since sometimes MIXED things have to revert to
+CONTEXT - see insert_plus.ml *)
+type mcodekind =
+ MINUS of (Ast.anything list list * token_info) ref
+ | PLUS
+ | CONTEXT of (Ast.anything Ast.befaft * token_info * token_info) ref
+ | MIXED of (Ast.anything Ast.befaft * token_info * token_info) ref
+
+type info = { line_start : int; line_end : int;
+ logical_start : int; logical_end : int;
+ attachable_start : bool; attachable_end : bool;
+ mcode_start : mcodekind list; mcode_end : mcodekind list;
+ column : int; offset : int;
+ (* the following are only for + code *)
+ strings_before : string list; strings_after : string list }
+
+type 'a mcode = 'a * arity * info * mcodekind * meta_pos ref (* pos, - only *)
+(* int ref is an index *)
+and 'a wrap =
+ { node : 'a;
+ info : info;
+ index : int ref;
+ mcodekind : mcodekind ref;
+ exp_ty : Type_cocci.typeC option ref; (* only for expressions *)
+ bef_aft : dots_bef_aft; (* only for statements *)
+ true_if_arg : bool; (* true if "arg_exp", only for exprs *)
+ true_if_test : bool; (* true if "test position", only for exprs *)
+ true_if_test_exp : bool;(* true if "test_exp from iso", only for exprs *)
+ (*nonempty if this represents the use of an iso*)
+ iso_info : (string*anything) list }
+
+and dots_bef_aft =
+ NoDots | AddingBetweenDots of statement | DroppingBetweenDots of statement
+
+(* for iso metavariables, true if they can only match nonmodified terms with
+ all metavariables unitary
+ for SP metavariables, true if the metavariable is unitary (valid up to
+ isomorphism phase only)
+ In SP, the only options are impure and context
+*)
+and pure = Impure | Pure | Context | PureContext (* pure and only context *)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+and 'a base_dots =
+ DOTS of 'a list
+ | CIRCLES of 'a list
+ | STARS of 'a list
+
+and 'a dots = 'a base_dots wrap
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+and base_ident =
+ Id of string mcode
+ | MetaId of Ast.meta_name mcode * ident list * pure
+ | MetaFunc of Ast.meta_name mcode * ident list * pure
+ | MetaLocalFunc of Ast.meta_name mcode * ident list * pure
+ | OptIdent of ident
+ | UniqueIdent of ident
+
+and ident = base_ident wrap
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+and base_expression =
+ Ident of ident
+ | Constant of Ast.constant mcode
+ | FunCall of expression * string mcode (* ( *) *
+ expression dots * string mcode (* ) *)
+ | Assignment of expression * Ast.assignOp mcode * expression *
+ bool (* true if it can match an initialization *)
+ | CondExpr of expression * string mcode (* ? *) * expression option *
+ string mcode (* : *) * expression
+ | Postfix of expression * Ast.fixOp mcode
+ | Infix of expression * Ast.fixOp mcode
+ | Unary of expression * Ast.unaryOp mcode
+ | Binary of expression * Ast.binaryOp mcode * expression
+ | Nested of expression * Ast.binaryOp mcode * expression
+ | Paren of string mcode (* ( *) * expression *
+ string mcode (* ) *)
+ | ArrayAccess of expression * string mcode (* [ *) * expression *
+ string mcode (* ] *)
+ | RecordAccess of expression * string mcode (* . *) * ident
+ | RecordPtAccess of expression * string mcode (* -> *) * ident
+ | Cast of string mcode (* ( *) * typeC * string mcode (* ) *) *
+ expression
+ | SizeOfExpr of string mcode (* sizeof *) * expression
+ | SizeOfType of string mcode (* sizeof *) * string mcode (* ( *) *
+ typeC * string mcode (* ) *)
+ | TypeExp of typeC (* type name used as an expression, only in args *)
+ | MetaErr of Ast.meta_name mcode * expression list * pure
+ | MetaExpr of Ast.meta_name mcode * expression list *
+ Type_cocci.typeC list option * Ast.form * pure
+ | MetaExprList of Ast.meta_name mcode (* only in arg lists *) *
+ listlen * pure
+ | EComma of string mcode (* only in arg lists *)
+ | DisjExpr of string mcode * expression list *
+ string mcode list (* the |s *) * string mcode
+ | NestExpr of string mcode * expression dots * string mcode *
+ expression option * Ast.multi
+ | Edots of string mcode (* ... *) * expression option
+ | Ecircles of string mcode (* ooo *) * expression option
+ | Estars of string mcode (* *** *) * expression option
+ | OptExp of expression
+ | UniqueExp of expression
+
+and expression = base_expression wrap
+
+and listlen = Ast.meta_name mcode option
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and base_typeC =
+ ConstVol of Ast.const_vol mcode * typeC
+ | BaseType of Ast.baseType mcode * Ast.sign mcode option
+ | ImplicitInt of Ast.sign mcode
+ | Pointer of typeC * string mcode (* * *)
+ | FunctionPointer of typeC *
+ string mcode(* ( *)*string mcode(* * *)*string mcode(* ) *)*
+ string mcode (* ( *)*parameter_list*string mcode(* ) *)
+ | FunctionType of typeC option *
+ string mcode (* ( *) * parameter_list *
+ string mcode (* ) *)
+ | Array of typeC * string mcode (* [ *) *
+ expression option * string mcode (* ] *)
+ | StructUnionName of Ast.structUnion mcode * ident option (* name *)
+ | StructUnionDef of typeC (* either StructUnionName or metavar *) *
+ string mcode (* { *) * declaration dots * string mcode (* } *)
+ | TypeName of string mcode
+ | MetaType of Ast.meta_name mcode * pure
+ | DisjType of string mcode * typeC list * (* only after iso *)
+ string mcode list (* the |s *) * string mcode
+ | OptType of typeC
+ | UniqueType of typeC
+
+and typeC = base_typeC wrap
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and base_declaration =
+ Init of Ast.storage mcode option * typeC * ident * string mcode (*=*) *
+ initialiser * string mcode (*;*)
+ | UnInit of Ast.storage mcode option * typeC * ident * string mcode (* ; *)
+ | TyDecl of typeC * string mcode (* ; *)
+ | MacroDecl of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *) * string mcode (* ; *)
+ | Typedef of string mcode (* typedef *) * typeC * typeC * string mcode (*;*)
+ | DisjDecl of string mcode * declaration list *
+ string mcode list (* the |s *) * string mcode
+ (* Ddots is for a structure declaration *)
+ | Ddots of string mcode (* ... *) * declaration option (* whencode *)
+ | OptDecl of declaration
+ | UniqueDecl of declaration
+
+and declaration = base_declaration wrap
+
+(* --------------------------------------------------------------------- *)
+(* Initializers *)
+
+and base_initialiser =
+ InitExpr of expression
+ | InitList of string mcode (*{*) * initialiser_list * string mcode (*}*)
+ | InitGccDotName of
+ string mcode (*.*) * ident (* name *) * string mcode (*=*) *
+ initialiser (* gccext: *)
+ | InitGccName of ident (* name *) * string mcode (*:*) *
+ initialiser
+ | InitGccIndex of
+ string mcode (*[*) * expression * string mcode (*]*) *
+ string mcode (*=*) * initialiser
+ | InitGccRange of
+ string mcode (*[*) * expression * string mcode (*...*) *
+ expression * string mcode (*]*) * string mcode (*=*) * initialiser
+ | IComma of string mcode (* , *)
+ | Idots of string mcode (* ... *) * initialiser option (* whencode *)
+ | OptIni of initialiser
+ | UniqueIni of initialiser
+
+and initialiser = base_initialiser wrap
+
+and initialiser_list = initialiser dots
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and base_parameterTypeDef =
+ VoidParam of typeC
+ | Param of typeC * ident option
+ | MetaParam of Ast.meta_name mcode * pure
+ | MetaParamList of Ast.meta_name mcode * listlen * pure
+ | PComma of string mcode
+ | Pdots of string mcode (* ... *)
+ | Pcircles of string mcode (* ooo *)
+ | OptParam of parameterTypeDef
+ | UniqueParam of parameterTypeDef
+
+and parameterTypeDef = base_parameterTypeDef wrap
+
+and parameter_list = parameterTypeDef dots
+
+(* --------------------------------------------------------------------- *)
+(* #define Parameters *)
+
+and base_define_param =
+ DParam of ident
+ | DPComma of string mcode
+ | DPdots of string mcode (* ... *)
+ | DPcircles of string mcode (* ooo *)
+ | OptDParam of define_param
+ | UniqueDParam of define_param
+
+and define_param = base_define_param wrap
+
+and base_define_parameters =
+ NoParams
+ | DParams of string mcode(*( *) * define_param dots * string mcode(* )*)
+
+and define_parameters = base_define_parameters wrap
+
+(* --------------------------------------------------------------------- *)
+(* Statement*)
+
+and base_statement =
+ Decl of (info * mcodekind) (* before the decl *) * declaration
+ | Seq of string mcode (* { *) * statement dots *
+ string mcode (* } *)
+ | ExprStatement of expression * string mcode (*;*)
+ | IfThen of string mcode (* if *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ statement * (info * mcodekind) (* after info *)
+ | IfThenElse of string mcode (* if *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ statement * string mcode (* else *) * statement *
+ (info * mcodekind)
+ | While of string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ statement * (info * mcodekind) (* after info *)
+ | Do of string mcode (* do *) * statement *
+ string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ string mcode (* ; *)
+ | For of string mcode (* for *) * string mcode (* ( *) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (* ) *) * statement *
+ (info * mcodekind) (* after info *)
+ | Iterator of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *) *
+ statement * (info * mcodekind) (* after info *)
+ | Switch of string mcode (* switch *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) * string mcode (* { *) *
+ case_line dots * string mcode (* } *)
+ | Break of string mcode (* break *) * string mcode (* ; *)
+ | Continue of string mcode (* continue *) * string mcode (* ; *)
+ | Label of ident * string mcode (* : *)
+ | Goto of string mcode (* goto *) * ident * string mcode (* ; *)
+ | Return of string mcode (* return *) * string mcode (* ; *)
+ | ReturnExpr of string mcode (* return *) * expression *
+ string mcode (* ; *)
+ | MetaStmt of Ast.meta_name mcode * pure
+ | MetaStmtList of Ast.meta_name mcode(*only in statement lists*) * pure
+ | Exp of expression (* only in dotted statement lists *)
+ | TopExp of expression (* for macros body *)
+ | Ty of typeC (* only at top level *)
+ | Disj of string mcode * statement dots list *
+ string mcode list (* the |s *) * string mcode
+ | Nest of string mcode * statement dots * string mcode *
+ (statement dots,statement) whencode list * Ast.multi
+ | Dots of string mcode (* ... *) *
+ (statement dots,statement) whencode list
+ | Circles of string mcode (* ooo *) *
+ (statement dots,statement) whencode list
+ | Stars of string mcode (* *** *) *
+ (statement dots,statement) whencode list
+ | FunDecl of (info * mcodekind) (* before the function decl *) *
+ fninfo list * ident (* name *) *
+ string mcode (* ( *) * parameter_list * string mcode (* ) *) *
+ string mcode (* { *) * statement dots *
+ string mcode (* } *)
+ | Include of string mcode (* #include *) * Ast.inc_file mcode (* file *)
+ | Define of string mcode (* #define *) * ident (* name *) *
+ define_parameters (*params*) * statement dots
+ | OptStm of statement
+ | UniqueStm of statement
+
+and fninfo =
+ FStorage of Ast.storage mcode
+ | FType of typeC
+ | FInline of string mcode
+ | FAttr of string mcode
+
+and ('a,'b) whencode =
+ WhenNot of 'a
+ | WhenAlways of 'b
+ | WhenModifier of Ast.when_modifier
+
+and statement = base_statement wrap
+
+and base_case_line =
+ Default of string mcode (* default *) * string mcode (*:*) * statement dots
+ | Case of string mcode (* case *) * expression * string mcode (*:*) *
+ statement dots
+ | OptCase of case_line
+
+and case_line = base_case_line wrap
+
+(* --------------------------------------------------------------------- *)
+(* Positions *)
+
+and meta_pos =
+ MetaPos of Ast.meta_name mcode * Ast.meta_name list * Ast.meta_collect
+ | NoMetaPos
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and base_top_level =
+ DECL of statement
+ | CODE of statement dots
+ | FILEINFO of string mcode (* old file *) * string mcode (* new file *)
+ | ERRORWORDS of expression list
+ | OTHER of statement (* temporary, disappears after top_level.ml *)
+
+and top_level = base_top_level wrap
+and rule = top_level list
+
+and parsed_rule =
+ CocciRule of
+ (rule * Ast.metavar list *
+ (string list * string list * Ast.dependency * string * Ast.exists)) *
+ (rule * Ast.metavar list)
+ | ScriptRule of
+ string * Ast.dependency * (string * Ast.meta_name) list * string
+
+(* --------------------------------------------------------------------- *)
+
+and anything =
+ DotsExprTag of expression dots
+ | DotsInitTag of initialiser dots
+ | DotsParamTag of parameterTypeDef dots
+ | DotsStmtTag of statement dots
+ | DotsDeclTag of declaration dots
+ | DotsCaseTag of case_line dots
+ | IdentTag of ident
+ | ExprTag of expression
+ | ArgExprTag of expression (* for isos *)
+ | TestExprTag of expression (* for isos *)
+ | TypeCTag of typeC
+ | ParamTag of parameterTypeDef
+ | InitTag of initialiser
+ | DeclTag of declaration
+ | StmtTag of statement
+ | CaseLineTag of case_line
+ | TopTag of top_level
+ | IsoWhenTag of Ast.when_modifier
+ | MetaPosTag of meta_pos
+
+let dotsExpr x = DotsExprTag x
+let dotsParam x = DotsParamTag x
+let dotsInit x = DotsInitTag x
+let dotsStmt x = DotsStmtTag x
+let dotsDecl x = DotsDeclTag x
+let dotsCase x = DotsCaseTag x
+let ident x = IdentTag x
+let expr x = ExprTag x
+let typeC x = TypeCTag x
+let param x = ParamTag x
+let ini x = InitTag x
+let decl x = DeclTag x
+let stmt x = StmtTag x
+let case_line x = CaseLineTag x
+let top x = TopTag x
+
+(* --------------------------------------------------------------------- *)
+(* Avoid cluttering the parser. Calculated in compute_lines.ml. *)
+
+let default_info _ = (* why is this a function? *)
+ { line_start = -1; line_end = -1;
+ logical_start = -1; logical_end = -1;
+ attachable_start = true; attachable_end = true;
+ mcode_start = []; mcode_end = [];
+ column = -1; offset = -1; strings_before = []; strings_after = [] }
+
+let default_befaft _ =
+ MIXED(ref (Ast.NOTHING,default_token_info,default_token_info))
+let context_befaft _ =
+ CONTEXT(ref (Ast.NOTHING,default_token_info,default_token_info))
+
+let wrap x =
+ { node = x;
+ info = default_info();
+ index = ref (-1);
+ mcodekind = ref (default_befaft());
+ exp_ty = ref None;
+ bef_aft = NoDots;
+ true_if_arg = false;
+ true_if_test = false;
+ true_if_test_exp = false;
+ iso_info = [] }
+let context_wrap x =
+ { node = x;
+ info = default_info();
+ index = ref (-1);
+ mcodekind = ref (context_befaft());
+ exp_ty = ref None;
+ bef_aft = NoDots;
+ true_if_arg = false;
+ true_if_test = false;
+ true_if_test_exp = false;
+ iso_info = [] }
+let unwrap x = x.node
+let unwrap_mcode (x,_,_,_,_) = x
+let rewrap model x = { model with node = x }
+let rewrap_mcode (_,arity,info,mcodekind,pos) x = (x,arity,info,mcodekind,pos)
+let copywrap model x =
+ { model with node = x; index = ref !(model.index);
+ mcodekind = ref !(model.mcodekind); exp_ty = ref !(model.exp_ty)}
+let get_pos (_,_,_,_,x) = !x
+let get_pos_ref (_,_,_,_,x) = x
+let set_pos pos (m,arity,info,mcodekind,_) = (m,arity,info,mcodekind,ref pos)
+let get_info x = x.info
+let set_info x info = {x with info = info}
+let get_line x = x.info.line_start
+let get_line_end x = x.info.line_end
+let get_index x = !(x.index)
+let set_index x i = x.index := i
+let get_mcodekind x = !(x.mcodekind)
+let get_mcode_mcodekind (_,_,_,mcodekind,_) = mcodekind
+let get_mcodekind_ref x = x.mcodekind
+let set_mcodekind x mk = x.mcodekind := mk
+let set_type x t = x.exp_ty := t
+let get_type x = !(x.exp_ty)
+let get_dots_bef_aft x = x.bef_aft
+let set_dots_bef_aft x dots_bef_aft = {x with bef_aft = dots_bef_aft}
+let get_arg_exp x = x.true_if_arg
+let set_arg_exp x = {x with true_if_arg = true}
+let get_test_pos x = x.true_if_test
+let set_test_pos x = {x with true_if_test = true}
+let get_test_exp x = x.true_if_test_exp
+let set_test_exp x = {x with true_if_test_exp = true}
+let get_iso x = x.iso_info
+let set_iso x i = if !Flag.track_iso_usage then {x with iso_info = i} else x
+let set_mcode_data data (_,ar,info,mc,pos) = (data,ar,info,mc,pos)
+
+(* --------------------------------------------------------------------- *)
+
+(* unique indices, for mcode and tree nodes *)
+let index_counter = ref 0
+let fresh_index _ = let cur = !index_counter in index_counter := cur + 1; cur
+
+(* --------------------------------------------------------------------- *)
+
+let undots d =
+ match unwrap d with
+ | DOTS e -> e
+ | CIRCLES e -> e
+ | STARS e -> e
+
+(* --------------------------------------------------------------------- *)
+
+let rec ast0_type_to_type ty =
+ match unwrap ty with
+ ConstVol(cv,ty) -> Type_cocci.ConstVol(const_vol cv,ast0_type_to_type ty)
+ | BaseType(bty,None) ->
+ Type_cocci.BaseType(baseType bty,None)
+ | BaseType(bty,Some sgn) ->
+ Type_cocci.BaseType(baseType bty,Some (sign sgn))
+ | ImplicitInt(sgn) ->
+ let bty = Type_cocci.IntType in
+ Type_cocci.BaseType(bty,Some (sign sgn))
+ | Pointer(ty,_) -> Type_cocci.Pointer(ast0_type_to_type ty)
+ | FunctionPointer(ty,_,_,_,_,params,_) ->
+ Type_cocci.FunctionPointer(ast0_type_to_type ty)
+ | FunctionType _ -> failwith "not supported"
+ | Array(ety,_,_,_) -> Type_cocci.Array(ast0_type_to_type ety)
+ | StructUnionName(su,Some tag) ->
+ (match unwrap tag with
+ Id(tag) ->
+ Type_cocci.StructUnionName(structUnion su,false,unwrap_mcode tag)
+ | MetaId(tag,_,_) ->
+ (Printf.printf
+ "warning: struct/union with a metavariable name detected.\n";
+ Printf.printf
+ "For type checking assuming the name of the metavariable is the name of the type\n";
+ let (rule,tag) = unwrap_mcode tag in
+ Type_cocci.StructUnionName(structUnion su,true,rule^tag))
+ | _ -> failwith "unexpected struct/union type name")
+ | StructUnionName(su,None) -> failwith "nameless structure - what to do???"
+ | StructUnionDef(ty,_,_,_) -> ast0_type_to_type ty
+ | TypeName(name) -> Type_cocci.TypeName(unwrap_mcode name)
+ | MetaType(name,_) ->
+ Type_cocci.MetaType(unwrap_mcode name,Type_cocci.Unitary,false)
+ | DisjType(_,types,_,_) -> failwith "unexpected DisjType"
+ | OptType(ty) | UniqueType(ty) ->
+ ast0_type_to_type ty
+
+and baseType t =
+ match unwrap_mcode t with
+ Ast.VoidType -> Type_cocci.VoidType
+ | Ast.CharType -> Type_cocci.CharType
+ | Ast.ShortType -> Type_cocci.ShortType
+ | Ast.IntType -> Type_cocci.IntType
+ | Ast.DoubleType -> Type_cocci.DoubleType
+ | Ast.FloatType -> Type_cocci.FloatType
+ | Ast.LongType -> Type_cocci.LongType
+
+and structUnion t =
+ match unwrap_mcode t with
+ Ast.Struct -> Type_cocci.Struct
+ | Ast.Union -> Type_cocci.Union
+
+and sign t =
+ match unwrap_mcode t with
+ Ast.Signed -> Type_cocci.Signed
+ | Ast.Unsigned -> Type_cocci.Unsigned
+
+and const_vol t =
+ match unwrap_mcode t with
+ Ast.Const -> Type_cocci.Const
+ | Ast.Volatile -> Type_cocci.Volatile
+
+(* --------------------------------------------------------------------- *)
+(* this function is a rather minimal attempt. the problem is that information
+has been lost. but since it is only used for metavariable types in the isos,
+perhaps it doesn't matter *)
+let make_mcode x = (x,NONE,default_info(),context_befaft(),ref NoMetaPos)
+let make_mcode_info x info = (x,NONE,info,context_befaft(),ref NoMetaPos)
+
+exception TyConv
+
+let rec reverse_type ty =
+ match ty with
+ Type_cocci.ConstVol(cv,ty) ->
+ ConstVol(reverse_const_vol cv,wrap(reverse_type ty))
+ | Type_cocci.BaseType(bty,None) ->
+ BaseType(reverse_baseType bty,None)
+ | Type_cocci.BaseType(bty,Some sgn) ->
+ BaseType(reverse_baseType bty,Some (reverse_sign sgn))
+ | Type_cocci.Pointer(ty) ->
+ Pointer(wrap(reverse_type ty),make_mcode "*")
+ | Type_cocci.StructUnionName(su,mv,tag) ->
+ if mv
+ then
+ (* not right... *)
+ StructUnionName(reverse_structUnion su,
+ Some(wrap(MetaId(make_mcode ("",tag),[],Impure))))
+ else
+ StructUnionName(reverse_structUnion su,
+ Some (wrap(Id(make_mcode tag))))
+ | Type_cocci.TypeName(name) -> TypeName(make_mcode name)
+ | Type_cocci.MetaType(name,_,_) ->
+ MetaType(make_mcode name,Impure(*not really right*))
+ | _ -> raise TyConv
+
+and reverse_baseType t =
+ make_mcode
+ (match t with
+ Type_cocci.VoidType -> Ast.VoidType
+ | Type_cocci.CharType -> Ast.CharType
+ | Type_cocci.BoolType -> Ast.IntType
+ | Type_cocci.ShortType -> Ast.ShortType
+ | Type_cocci.IntType -> Ast.IntType
+ | Type_cocci.DoubleType -> Ast.DoubleType
+ | Type_cocci.FloatType -> Ast.FloatType
+ | Type_cocci.LongType -> Ast.LongType)
+
+and reverse_structUnion t =
+ make_mcode
+ (match t with
+ Type_cocci.Struct -> Ast.Struct
+ | Type_cocci.Union -> Ast.Union)
+
+and reverse_sign t =
+ make_mcode
+ (match t with
+ Type_cocci.Signed -> Ast.Signed
+ | Type_cocci.Unsigned -> Ast.Unsigned)
+
+and reverse_const_vol t =
+ make_mcode
+ (match t with
+ Type_cocci.Const -> Ast.Const
+ | Type_cocci.Volatile -> Ast.Volatile)
+
+(* --------------------------------------------------------------------- *)
+
+let lub_pure x y =
+ match (x,y) with
+ (Impure,_) | (_,Impure) -> Impure
+ | (Pure,Context) | (Context,Pure) -> Impure
+ | (Pure,_) | (_,Pure) -> Pure
+ | (_,Context) | (Context,_) -> Context
+ | _ -> PureContext
+
+(* --------------------------------------------------------------------- *)
+
+let rule_name = ref "" (* for the convenience of the parser *)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+type arity = OPT | UNIQUE | NONE
+
+type token_info =
+ { tline_start : int; tline_end : int;
+ left_offset : int; right_offset : int }
+let default_token_info =
+ { tline_start = -1; tline_end = -1; left_offset = -1; right_offset = -1 }
+
+(* MIXED is like CONTEXT, since sometimes MIXED things have to revert to
+CONTEXT - see insert_plus.ml *)
+type mcodekind =
+ MINUS of (Ast.anything list list * token_info) ref
+ | PLUS
+ | CONTEXT of (Ast.anything Ast.befaft * token_info * token_info) ref
+ | MIXED of (Ast.anything Ast.befaft * token_info * token_info) ref
+
+type info = { line_start : int; line_end : int;
+ logical_start : int; logical_end : int;
+ attachable_start : bool; attachable_end : bool;
+ mcode_start : mcodekind list; mcode_end : mcodekind list;
+ column : int; offset : int;
+ (* the following are only for + code *)
+ strings_before : string list; strings_after : string list }
+
+type 'a mcode = 'a * arity * info * mcodekind * meta_pos ref (* pos, - only *)
+(* int ref is an index *)
+and 'a wrap =
+ { node : 'a;
+ info : info;
+ index : int ref;
+ mcodekind : mcodekind ref;
+ exp_ty : Type_cocci.typeC option ref; (* only for expressions *)
+ bef_aft : dots_bef_aft; (* only for statements *)
+ true_if_arg : bool; (* true if "arg_exp", only for exprs *)
+ true_if_test : bool; (* true if "test position", only for exprs *)
+ true_if_test_exp : bool;(* true if "test_exp from iso", only for exprs *)
+ (*nonempty if this represents the use of an iso*)
+ iso_info : (string*anything) list }
+
+and dots_bef_aft =
+ NoDots | AddingBetweenDots of statement | DroppingBetweenDots of statement
+
+(* for iso metavariables, true if they can only match nonmodified terms with
+ all metavariables unitary
+ for SP metavariables, true if the metavariable is unitary (valid up to
+ isomorphism phase only)
+ In SP, the only options are impure and context
+*)
+and pure = Impure | Pure | Context | PureContext (* pure and only context *)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+and 'a base_dots =
+ DOTS of 'a list
+ | CIRCLES of 'a list
+ | STARS of 'a list
+
+and 'a dots = 'a base_dots wrap
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+and base_ident =
+ Id of string mcode
+ | MetaId of Ast.meta_name mcode * ident list * pure
+ | MetaFunc of Ast.meta_name mcode * ident list * pure
+ | MetaLocalFunc of Ast.meta_name mcode * ident list * pure
+ | OptIdent of ident
+ | UniqueIdent of ident
+
+and ident = base_ident wrap
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+and base_expression =
+ Ident of ident
+ | Constant of Ast.constant mcode
+ | FunCall of expression * string mcode (* ( *) *
+ expression dots * string mcode (* ) *)
+ | Assignment of expression * Ast.assignOp mcode * expression *
+ bool (* true if it can match an initialization *)
+ | CondExpr of expression * string mcode (* ? *) * expression option *
+ string mcode (* : *) * expression
+ | Postfix of expression * Ast.fixOp mcode
+ | Infix of expression * Ast.fixOp mcode
+ | Unary of expression * Ast.unaryOp mcode
+ | Binary of expression * Ast.binaryOp mcode * expression
+ | Nested of expression * Ast.binaryOp mcode * expression
+ | Paren of string mcode (* ( *) * expression *
+ string mcode (* ) *)
+ | ArrayAccess of expression * string mcode (* [ *) * expression *
+ string mcode (* ] *)
+ | RecordAccess of expression * string mcode (* . *) * ident
+ | RecordPtAccess of expression * string mcode (* -> *) * ident
+ | Cast of string mcode (* ( *) * typeC * string mcode (* ) *) *
+ expression
+ | SizeOfExpr of string mcode (* sizeof *) * expression
+ | SizeOfType of string mcode (* sizeof *) * string mcode (* ( *) *
+ typeC * string mcode (* ) *)
+ | TypeExp of typeC (* type name used as an expression, only in args *)
+ | MetaErr of Ast.meta_name mcode * expression list * pure
+ | MetaExpr of Ast.meta_name mcode * expression list *
+ Type_cocci.typeC list option * Ast.form * pure
+ | MetaExprList of Ast.meta_name mcode (* only in arg lists *) *
+ listlen * pure
+ | EComma of string mcode (* only in arg lists *)
+ | DisjExpr of string mcode * expression list *
+ string mcode list (* the |s *) * string mcode
+ | NestExpr of string mcode * expression dots * string mcode *
+ expression option * Ast.multi
+ | Edots of string mcode (* ... *) * expression option
+ | Ecircles of string mcode (* ooo *) * expression option
+ | Estars of string mcode (* *** *) * expression option
+ | OptExp of expression
+ | UniqueExp of expression
+
+and expression = base_expression wrap
+
+and listlen = Ast.meta_name mcode option
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and base_typeC =
+ ConstVol of Ast.const_vol mcode * typeC
+ | BaseType of Ast.baseType mcode * Ast.sign mcode option
+ | ImplicitInt of Ast.sign mcode
+ | Pointer of typeC * string mcode (* * *)
+ | FunctionPointer of typeC *
+ string mcode(* ( *)*string mcode(* * *)*string mcode(* ) *)*
+ string mcode (* ( *)*parameter_list*string mcode(* ) *)
+ | FunctionType of typeC option *
+ string mcode (* ( *) * parameter_list *
+ string mcode (* ) *)
+ | Array of typeC * string mcode (* [ *) *
+ expression option * string mcode (* ] *)
+ | StructUnionName of Ast.structUnion mcode * ident option (* name *)
+ | StructUnionDef of typeC (* either StructUnionName or metavar *) *
+ string mcode (* { *) * declaration dots * string mcode (* } *)
+ | TypeName of string mcode
+ | MetaType of Ast.meta_name mcode * pure
+ | DisjType of string mcode * typeC list * (* only after iso *)
+ string mcode list (* the |s *) * string mcode
+ | OptType of typeC
+ | UniqueType of typeC
+
+and typeC = base_typeC wrap
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and base_declaration =
+ Init of Ast.storage mcode option * typeC * ident * string mcode (*=*) *
+ initialiser * string mcode (*;*)
+ | UnInit of Ast.storage mcode option * typeC * ident * string mcode (* ; *)
+ | TyDecl of typeC * string mcode (* ; *)
+ | MacroDecl of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *) * string mcode (* ; *)
+ | Typedef of string mcode (* typedef *) * typeC * typeC * string mcode (*;*)
+ | DisjDecl of string mcode * declaration list *
+ string mcode list (* the |s *) * string mcode
+ (* Ddots is for a structure declaration *)
+ | Ddots of string mcode (* ... *) * declaration option (* whencode *)
+ | OptDecl of declaration
+ | UniqueDecl of declaration
+
+and declaration = base_declaration wrap
+
+(* --------------------------------------------------------------------- *)
+(* Initializers *)
+
+and base_initialiser =
+ InitExpr of expression
+ | InitList of string mcode (*{*) * initialiser_list * string mcode (*}*)
+ | InitGccDotName of
+ string mcode (*.*) * ident (* name *) * string mcode (*=*) *
+ initialiser (* gccext: *)
+ | InitGccName of ident (* name *) * string mcode (*:*) *
+ initialiser
+ | InitGccIndex of
+ string mcode (*[*) * expression * string mcode (*]*) *
+ string mcode (*=*) * initialiser
+ | InitGccRange of
+ string mcode (*[*) * expression * string mcode (*...*) *
+ expression * string mcode (*]*) * string mcode (*=*) * initialiser
+ | IComma of string mcode (* , *)
+ | Idots of string mcode (* ... *) * initialiser option (* whencode *)
+ | OptIni of initialiser
+ | UniqueIni of initialiser
+
+and initialiser = base_initialiser wrap
+
+and initialiser_list = initialiser dots
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and base_parameterTypeDef =
+ VoidParam of typeC
+ | Param of typeC * ident option
+ | MetaParam of Ast.meta_name mcode * pure
+ | MetaParamList of Ast.meta_name mcode * listlen * pure
+ | PComma of string mcode
+ | Pdots of string mcode (* ... *)
+ | Pcircles of string mcode (* ooo *)
+ | OptParam of parameterTypeDef
+ | UniqueParam of parameterTypeDef
+
+and parameterTypeDef = base_parameterTypeDef wrap
+
+and parameter_list = parameterTypeDef dots
+
+(* --------------------------------------------------------------------- *)
+(* #define Parameters *)
+
+and base_define_param =
+ DParam of ident
+ | DPComma of string mcode
+ | DPdots of string mcode (* ... *)
+ | DPcircles of string mcode (* ooo *)
+ | OptDParam of define_param
+ | UniqueDParam of define_param
+
+and define_param = base_define_param wrap
+
+and base_define_parameters =
+ NoParams
+ | DParams of string mcode(*( *) * define_param dots * string mcode(* )*)
+
+and define_parameters = base_define_parameters wrap
+
+(* --------------------------------------------------------------------- *)
+(* Statement*)
+
+and base_statement =
+ Decl of (info * mcodekind) (* before the decl *) * declaration
+ | Seq of string mcode (* { *) * statement dots *
+ string mcode (* } *)
+ | ExprStatement of expression * string mcode (*;*)
+ | IfThen of string mcode (* if *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ statement * (info * mcodekind) (* after info *)
+ | IfThenElse of string mcode (* if *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ statement * string mcode (* else *) * statement *
+ (info * mcodekind)
+ | While of string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ statement * (info * mcodekind) (* after info *)
+ | Do of string mcode (* do *) * statement *
+ string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ string mcode (* ; *)
+ | For of string mcode (* for *) * string mcode (* ( *) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (* ) *) * statement *
+ (info * mcodekind) (* after info *)
+ | Iterator of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *) *
+ statement * (info * mcodekind) (* after info *)
+ | Switch of string mcode (* switch *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) * string mcode (* { *) *
+ case_line dots * string mcode (* } *)
+ | Break of string mcode (* break *) * string mcode (* ; *)
+ | Continue of string mcode (* continue *) * string mcode (* ; *)
+ | Label of ident * string mcode (* : *)
+ | Goto of string mcode (* goto *) * ident * string mcode (* ; *)
+ | Return of string mcode (* return *) * string mcode (* ; *)
+ | ReturnExpr of string mcode (* return *) * expression *
+ string mcode (* ; *)
+ | MetaStmt of Ast.meta_name mcode * pure
+ | MetaStmtList of Ast.meta_name mcode(*only in statement lists*) * pure
+ | Exp of expression (* only in dotted statement lists *)
+ | TopExp of expression (* for macros body *)
+ | Ty of typeC (* only at top level *)
+ | Disj of string mcode * statement dots list *
+ string mcode list (* the |s *) * string mcode
+ | Nest of string mcode * statement dots * string mcode *
+ (statement dots,statement) whencode list * Ast.multi
+ | Dots of string mcode (* ... *) *
+ (statement dots,statement) whencode list
+ | Circles of string mcode (* ooo *) *
+ (statement dots,statement) whencode list
+ | Stars of string mcode (* *** *) *
+ (statement dots,statement) whencode list
+ | FunDecl of (info * mcodekind) (* before the function decl *) *
+ fninfo list * ident (* name *) *
+ string mcode (* ( *) * parameter_list * string mcode (* ) *) *
+ string mcode (* { *) * statement dots *
+ string mcode (* } *)
+ | Include of string mcode (* #include *) * Ast.inc_file mcode (* file *)
+ | Define of string mcode (* #define *) * ident (* name *) *
+ define_parameters (*params*) * statement dots
+ | OptStm of statement
+ | UniqueStm of statement
+
+and fninfo =
+ FStorage of Ast.storage mcode
+ | FType of typeC
+ | FInline of string mcode
+ | FAttr of string mcode
+
+and ('a,'b) whencode =
+ WhenNot of 'a
+ | WhenAlways of 'b
+ | WhenModifier of Ast.when_modifier
+ | WhenNotTrue of expression
+ | WhenNotFalse of expression
+
+and statement = base_statement wrap
+
+and base_case_line =
+ Default of string mcode (* default *) * string mcode (*:*) * statement dots
+ | Case of string mcode (* case *) * expression * string mcode (*:*) *
+ statement dots
+ | OptCase of case_line
+
+and case_line = base_case_line wrap
+
+(* --------------------------------------------------------------------- *)
+(* Positions *)
+
+and meta_pos =
+ MetaPos of Ast.meta_name mcode * Ast.meta_name list * Ast.meta_collect
+ | NoMetaPos
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and base_top_level =
+ DECL of statement
+ | CODE of statement dots
+ | FILEINFO of string mcode (* old file *) * string mcode (* new file *)
+ | ERRORWORDS of expression list
+ | OTHER of statement (* temporary, disappears after top_level.ml *)
+
+and top_level = base_top_level wrap
+and rule = top_level list
+
+and parsed_rule =
+ CocciRule of
+ (rule * Ast.metavar list *
+ (string list * string list * Ast.dependency * string * Ast.exists)) *
+ (rule * Ast.metavar list)
+ | ScriptRule of
+ string * Ast.dependency * (string * Ast.meta_name) list * string
+
+(* --------------------------------------------------------------------- *)
+
+and anything =
+ DotsExprTag of expression dots
+ | DotsInitTag of initialiser dots
+ | DotsParamTag of parameterTypeDef dots
+ | DotsStmtTag of statement dots
+ | DotsDeclTag of declaration dots
+ | DotsCaseTag of case_line dots
+ | IdentTag of ident
+ | ExprTag of expression
+ | ArgExprTag of expression (* for isos *)
+ | TestExprTag of expression (* for isos *)
+ | TypeCTag of typeC
+ | ParamTag of parameterTypeDef
+ | InitTag of initialiser
+ | DeclTag of declaration
+ | StmtTag of statement
+ | CaseLineTag of case_line
+ | TopTag of top_level
+ | IsoWhenTag of Ast.when_modifier
+ | IsoWhenTTag of expression
+ | IsoWhenFTag of expression
+ | MetaPosTag of meta_pos
+
+let dotsExpr x = DotsExprTag x
+let dotsParam x = DotsParamTag x
+let dotsInit x = DotsInitTag x
+let dotsStmt x = DotsStmtTag x
+let dotsDecl x = DotsDeclTag x
+let dotsCase x = DotsCaseTag x
+let ident x = IdentTag x
+let expr x = ExprTag x
+let typeC x = TypeCTag x
+let param x = ParamTag x
+let ini x = InitTag x
+let decl x = DeclTag x
+let stmt x = StmtTag x
+let case_line x = CaseLineTag x
+let top x = TopTag x
+
+(* --------------------------------------------------------------------- *)
+(* Avoid cluttering the parser. Calculated in compute_lines.ml. *)
+
+let default_info _ = (* why is this a function? *)
+ { line_start = -1; line_end = -1;
+ logical_start = -1; logical_end = -1;
+ attachable_start = true; attachable_end = true;
+ mcode_start = []; mcode_end = [];
+ column = -1; offset = -1; strings_before = []; strings_after = [] }
+
+let default_befaft _ =
+ MIXED(ref (Ast.NOTHING,default_token_info,default_token_info))
+let context_befaft _ =
+ CONTEXT(ref (Ast.NOTHING,default_token_info,default_token_info))
+
+let wrap x =
+ { node = x;
+ info = default_info();
+ index = ref (-1);
+ mcodekind = ref (default_befaft());
+ exp_ty = ref None;
+ bef_aft = NoDots;
+ true_if_arg = false;
+ true_if_test = false;
+ true_if_test_exp = false;
+ iso_info = [] }
+let context_wrap x =
+ { node = x;
+ info = default_info();
+ index = ref (-1);
+ mcodekind = ref (context_befaft());
+ exp_ty = ref None;
+ bef_aft = NoDots;
+ true_if_arg = false;
+ true_if_test = false;
+ true_if_test_exp = false;
+ iso_info = [] }
+let unwrap x = x.node
+let unwrap_mcode (x,_,_,_,_) = x
+let rewrap model x = { model with node = x }
+let rewrap_mcode (_,arity,info,mcodekind,pos) x = (x,arity,info,mcodekind,pos)
+let copywrap model x =
+ { model with node = x; index = ref !(model.index);
+ mcodekind = ref !(model.mcodekind); exp_ty = ref !(model.exp_ty)}
+let get_pos (_,_,_,_,x) = !x
+let get_pos_ref (_,_,_,_,x) = x
+let set_pos pos (m,arity,info,mcodekind,_) = (m,arity,info,mcodekind,ref pos)
+let get_info x = x.info
+let set_info x info = {x with info = info}
+let get_line x = x.info.line_start
+let get_line_end x = x.info.line_end
+let get_index x = !(x.index)
+let set_index x i = x.index := i
+let get_mcodekind x = !(x.mcodekind)
+let get_mcode_mcodekind (_,_,_,mcodekind,_) = mcodekind
+let get_mcodekind_ref x = x.mcodekind
+let set_mcodekind x mk = x.mcodekind := mk
+let set_type x t = x.exp_ty := t
+let get_type x = !(x.exp_ty)
+let get_dots_bef_aft x = x.bef_aft
+let set_dots_bef_aft x dots_bef_aft = {x with bef_aft = dots_bef_aft}
+let get_arg_exp x = x.true_if_arg
+let set_arg_exp x = {x with true_if_arg = true}
+let get_test_pos x = x.true_if_test
+let set_test_pos x = {x with true_if_test = true}
+let get_test_exp x = x.true_if_test_exp
+let set_test_exp x = {x with true_if_test_exp = true}
+let get_iso x = x.iso_info
+let set_iso x i = if !Flag.track_iso_usage then {x with iso_info = i} else x
+let set_mcode_data data (_,ar,info,mc,pos) = (data,ar,info,mc,pos)
+
+(* --------------------------------------------------------------------- *)
+
+(* unique indices, for mcode and tree nodes *)
+let index_counter = ref 0
+let fresh_index _ = let cur = !index_counter in index_counter := cur + 1; cur
+
+(* --------------------------------------------------------------------- *)
+
+let undots d =
+ match unwrap d with
+ | DOTS e -> e
+ | CIRCLES e -> e
+ | STARS e -> e
+
+(* --------------------------------------------------------------------- *)
+
+let rec ast0_type_to_type ty =
+ match unwrap ty with
+ ConstVol(cv,ty) -> Type_cocci.ConstVol(const_vol cv,ast0_type_to_type ty)
+ | BaseType(bty,None) ->
+ Type_cocci.BaseType(baseType bty,None)
+ | BaseType(bty,Some sgn) ->
+ Type_cocci.BaseType(baseType bty,Some (sign sgn))
+ | ImplicitInt(sgn) ->
+ let bty = Type_cocci.IntType in
+ Type_cocci.BaseType(bty,Some (sign sgn))
+ | Pointer(ty,_) -> Type_cocci.Pointer(ast0_type_to_type ty)
+ | FunctionPointer(ty,_,_,_,_,params,_) ->
+ Type_cocci.FunctionPointer(ast0_type_to_type ty)
+ | FunctionType _ -> failwith "not supported"
+ | Array(ety,_,_,_) -> Type_cocci.Array(ast0_type_to_type ety)
+ | StructUnionName(su,Some tag) ->
+ (match unwrap tag with
+ Id(tag) ->
+ Type_cocci.StructUnionName(structUnion su,false,unwrap_mcode tag)
+ | MetaId(tag,_,_) ->
+ (Printf.printf
+ "warning: struct/union with a metavariable name detected.\n";
+ Printf.printf
+ "For type checking assuming the name of the metavariable is the name of the type\n";
+ let (rule,tag) = unwrap_mcode tag in
+ Type_cocci.StructUnionName(structUnion su,true,rule^tag))
+ | _ -> failwith "unexpected struct/union type name")
+ | StructUnionName(su,None) -> failwith "nameless structure - what to do???"
+ | StructUnionDef(ty,_,_,_) -> ast0_type_to_type ty
+ | TypeName(name) -> Type_cocci.TypeName(unwrap_mcode name)
+ | MetaType(name,_) ->
+ Type_cocci.MetaType(unwrap_mcode name,Type_cocci.Unitary,false)
+ | DisjType(_,types,_,_) -> failwith "unexpected DisjType"
+ | OptType(ty) | UniqueType(ty) ->
+ ast0_type_to_type ty
+
+and baseType t =
+ match unwrap_mcode t with
+ Ast.VoidType -> Type_cocci.VoidType
+ | Ast.CharType -> Type_cocci.CharType
+ | Ast.ShortType -> Type_cocci.ShortType
+ | Ast.IntType -> Type_cocci.IntType
+ | Ast.DoubleType -> Type_cocci.DoubleType
+ | Ast.FloatType -> Type_cocci.FloatType
+ | Ast.LongType -> Type_cocci.LongType
+
+and structUnion t =
+ match unwrap_mcode t with
+ Ast.Struct -> Type_cocci.Struct
+ | Ast.Union -> Type_cocci.Union
+
+and sign t =
+ match unwrap_mcode t with
+ Ast.Signed -> Type_cocci.Signed
+ | Ast.Unsigned -> Type_cocci.Unsigned
+
+and const_vol t =
+ match unwrap_mcode t with
+ Ast.Const -> Type_cocci.Const
+ | Ast.Volatile -> Type_cocci.Volatile
+
+(* --------------------------------------------------------------------- *)
+(* this function is a rather minimal attempt. the problem is that information
+has been lost. but since it is only used for metavariable types in the isos,
+perhaps it doesn't matter *)
+let make_mcode x = (x,NONE,default_info(),context_befaft(),ref NoMetaPos)
+let make_mcode_info x info = (x,NONE,info,context_befaft(),ref NoMetaPos)
+
+exception TyConv
+
+let rec reverse_type ty =
+ match ty with
+ Type_cocci.ConstVol(cv,ty) ->
+ ConstVol(reverse_const_vol cv,wrap(reverse_type ty))
+ | Type_cocci.BaseType(bty,None) ->
+ BaseType(reverse_baseType bty,None)
+ | Type_cocci.BaseType(bty,Some sgn) ->
+ BaseType(reverse_baseType bty,Some (reverse_sign sgn))
+ | Type_cocci.Pointer(ty) ->
+ Pointer(wrap(reverse_type ty),make_mcode "*")
+ | Type_cocci.StructUnionName(su,mv,tag) ->
+ if mv
+ then
+ (* not right... *)
+ StructUnionName(reverse_structUnion su,
+ Some(wrap(MetaId(make_mcode ("",tag),[],Impure))))
+ else
+ StructUnionName(reverse_structUnion su,
+ Some (wrap(Id(make_mcode tag))))
+ | Type_cocci.TypeName(name) -> TypeName(make_mcode name)
+ | Type_cocci.MetaType(name,_,_) ->
+ MetaType(make_mcode name,Impure(*not really right*))
+ | _ -> raise TyConv
+
+and reverse_baseType t =
+ make_mcode
+ (match t with
+ Type_cocci.VoidType -> Ast.VoidType
+ | Type_cocci.CharType -> Ast.CharType
+ | Type_cocci.BoolType -> Ast.IntType
+ | Type_cocci.ShortType -> Ast.ShortType
+ | Type_cocci.IntType -> Ast.IntType
+ | Type_cocci.DoubleType -> Ast.DoubleType
+ | Type_cocci.FloatType -> Ast.FloatType
+ | Type_cocci.LongType -> Ast.LongType)
+
+and reverse_structUnion t =
+ make_mcode
+ (match t with
+ Type_cocci.Struct -> Ast.Struct
+ | Type_cocci.Union -> Ast.Union)
+
+and reverse_sign t =
+ make_mcode
+ (match t with
+ Type_cocci.Signed -> Ast.Signed
+ | Type_cocci.Unsigned -> Ast.Unsigned)
+
+and reverse_const_vol t =
+ make_mcode
+ (match t with
+ Type_cocci.Const -> Ast.Const
+ | Type_cocci.Volatile -> Ast.Volatile)
+
+(* --------------------------------------------------------------------- *)
+
+let lub_pure x y =
+ match (x,y) with
+ (Impure,_) | (_,Impure) -> Impure
+ | (Pure,Context) | (Context,Pure) -> Impure
+ | (Pure,_) | (_,Pure) -> Pure
+ | (_,Context) | (Context,_) -> Context
+ | _ -> PureContext
+
+(* --------------------------------------------------------------------- *)
+
+let rule_name = ref "" (* for the convenience of the parser *)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Arities matter for the minus slice, but not for the plus slice. *)
+
+(* + only allowed on code in a nest (in_nest = true). ? only allowed on
+rule_elems, and on subterms if the context is ? also. *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module V0 = Visitor_ast0
+module V = Visitor_ast
+
+let unitary = Type_cocci.Unitary
+
+let ctr = ref 0
+let get_ctr _ =
+ let c = !ctr in
+ ctr := !ctr + 1;
+ c
+
+(* --------------------------------------------------------------------- *)
+(* Move plus tokens from the MINUS and CONTEXT structured nodes to the
+corresponding leftmost and rightmost mcodes *)
+
+let inline_mcodes =
+ let bind x y = () in
+ let option_default = () in
+ let mcode _ = () in
+ let do_nothing r k e =
+ k e;
+ let einfo = Ast0.get_info e in
+ match (Ast0.get_mcodekind e) with
+ Ast0.MINUS(replacements) ->
+ (match !replacements with
+ ([],_) -> ()
+ | replacements ->
+ let minus_try = function
+ (true,mc) ->
+ if List.for_all
+ (function
+ Ast0.MINUS(mreplacements) -> true | _ -> false)
+ mc
+ then
+ (List.iter
+ (function
+ Ast0.MINUS(mreplacements) ->
+ mreplacements := replacements
+ | _ -> ())
+ mc;
+ true)
+ else false
+ | _ -> false in
+ if not (minus_try(einfo.Ast0.attachable_start,
+ einfo.Ast0.mcode_start)
+ or
+ minus_try(einfo.Ast0.attachable_end,
+ einfo.Ast0.mcode_end))
+ then
+ failwith "minus tree should not have bad code on both sides")
+ | Ast0.CONTEXT(befaft)
+ | Ast0.MIXED(befaft) ->
+ let concat starter startinfo ender endinfo =
+ let lst =
+ match (starter,ender) with
+ ([],_) -> ender
+ | (_,[]) -> starter
+ | _ ->
+ if startinfo.Ast0.tline_end = endinfo.Ast0.tline_start
+ then (* put them in the same inner list *)
+ let last = List.hd (List.rev starter) in
+ let butlast = List.rev(List.tl(List.rev starter)) in
+ butlast @ (last@(List.hd ender)) :: (List.tl ender)
+ else starter @ ender in
+ (lst,
+ {endinfo with Ast0.tline_start = startinfo.Ast0.tline_start}) in
+ let attach_bef bef beforeinfo = function
+ (true,mcl) ->
+ List.iter
+ (function
+ Ast0.MINUS(mreplacements) ->
+ let (mrepl,tokeninfo) = !mreplacements in
+ mreplacements := concat bef beforeinfo mrepl tokeninfo
+ | Ast0.CONTEXT(mbefaft) ->
+ (match !mbefaft with
+ (Ast.BEFORE(mbef),mbeforeinfo,a) ->
+ let (newbef,newinfo) =
+ concat bef beforeinfo mbef mbeforeinfo in
+ mbefaft := (Ast.BEFORE(newbef),newinfo,a)
+ | (Ast.AFTER(maft),_,a) ->
+ mbefaft :=
+ (Ast.BEFOREAFTER(bef,maft),beforeinfo,a)
+ | (Ast.BEFOREAFTER(mbef,maft),mbeforeinfo,a) ->
+ let (newbef,newinfo) =
+ concat bef beforeinfo mbef mbeforeinfo in
+ mbefaft :=
+ (Ast.BEFOREAFTER(newbef,maft),newinfo,a)
+ | (Ast.NOTHING,_,a) ->
+ mbefaft := (Ast.BEFORE(bef),beforeinfo,a))
+ | _ -> failwith "unexpected annotation")
+ mcl
+ | _ ->
+ failwith
+ "context tree should not have bad code on both sides" in
+ let attach_aft aft afterinfo = function
+ (true,mcl) ->
+ List.iter
+ (function
+ Ast0.MINUS(mreplacements) ->
+ let (mrepl,tokeninfo) = !mreplacements in
+ mreplacements := concat mrepl tokeninfo aft afterinfo
+ | Ast0.CONTEXT(mbefaft) ->
+ (match !mbefaft with
+ (Ast.BEFORE(mbef),b,_) ->
+ mbefaft :=
+ (Ast.BEFOREAFTER(mbef,aft),b,afterinfo)
+ | (Ast.AFTER(maft),b,mafterinfo) ->
+ let (newaft,newinfo) =
+ concat maft mafterinfo aft afterinfo in
+ mbefaft := (Ast.AFTER(newaft),b,newinfo)
+ | (Ast.BEFOREAFTER(mbef,maft),b,mafterinfo) ->
+ let (newaft,newinfo) =
+ concat maft mafterinfo aft afterinfo in
+ mbefaft :=
+ (Ast.BEFOREAFTER(mbef,newaft),b,newinfo)
+ | (Ast.NOTHING,b,_) ->
+ mbefaft := (Ast.AFTER(aft),b,afterinfo))
+ | _ -> failwith "unexpected annotation")
+ mcl
+ | _ ->
+ failwith
+ "context tree should not have bad code on both sides" in
+ (match !befaft with
+ (Ast.BEFORE(bef),beforeinfo,_) ->
+ attach_bef bef beforeinfo
+ (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start)
+ | (Ast.AFTER(aft),_,afterinfo) ->
+ attach_aft aft afterinfo
+ (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
+ | (Ast.BEFOREAFTER(bef,aft),beforeinfo,afterinfo) ->
+ attach_bef bef beforeinfo
+ (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start);
+ attach_aft aft afterinfo
+ (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
+ | (Ast.NOTHING,_,_) -> ())
+ | Ast0.PLUS -> () in
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode mcode mcode
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing
+
+(* --------------------------------------------------------------------- *)
+(* For function declarations. Can't use the mcode at the root, because that
+might be mixed when the function contains ()s, where agglomeration of -s is
+not possible. *)
+
+let check_allminus =
+ let donothing r k e = k e in
+ let bind x y = x && y in
+ let option_default = true in
+ let mcode (_,_,_,mc,_) =
+ match mc with
+ Ast0.MINUS(r) -> let (plusses,_) = !r in plusses = []
+ | _ -> false in
+
+ (* special case for disj *)
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ List.for_all r.V0.combiner_expression expr_list
+ | _ -> k e in
+
+ let declaration r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjDecl(starter,decls,mids,ender) ->
+ List.for_all r.V0.combiner_declaration decls
+ | _ -> k e in
+
+ let typeC r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjType(starter,decls,mids,ender) ->
+ List.for_all r.V0.combiner_typeC decls
+ | _ -> k e in
+
+ let statement r k e =
+ match Ast0.unwrap e with
+ Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ List.for_all r.V0.combiner_statement_dots statement_dots_list
+ | _ -> k e in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode mcode mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing expression typeC donothing donothing declaration
+ statement donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+
+let get_option fn = function
+ None -> None
+ | Some x -> Some (fn x)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Mcode *)
+
+let convert_info info =
+ { Ast.line = info.Ast0.line_start; Ast.column = info.Ast0.column;
+ Ast.strbef = info.Ast0.strings_before;
+ Ast.straft = info.Ast0.strings_after; }
+
+let convert_mcodekind = function
+ Ast0.MINUS(replacements) ->
+ let (replacements,_) = !replacements in
+ Ast.MINUS(Ast.NoPos,replacements)
+ | Ast0.PLUS -> Ast.PLUS
+ | Ast0.CONTEXT(befaft) ->
+ let (befaft,_,_) = !befaft in Ast.CONTEXT(Ast.NoPos,befaft)
+ | Ast0.MIXED(_) -> failwith "not possible for mcode"
+
+let pos_mcode(term,_,info,mcodekind,pos) =
+ (* avoids a recursion problem *)
+ (term,convert_info info,convert_mcodekind mcodekind,Ast.NoMetaPos)
+
+let mcode(term,_,info,mcodekind,pos) =
+ let pos =
+ match !pos with
+ Ast0.MetaPos(pos,constraints,per) ->
+ Ast.MetaPos(pos_mcode pos,constraints,per,unitary,false)
+ | _ -> Ast.NoMetaPos in
+ (term,convert_info info,convert_mcodekind mcodekind,pos)
+
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+let wrap ast line isos =
+ {(Ast.make_term ast) with Ast.node_line = line;
+ Ast.iso_info = isos}
+
+let rewrap ast0 isos ast =
+ wrap ast ((Ast0.get_info ast0).Ast0.line_start) isos
+
+let no_isos = []
+
+(* no isos on tokens *)
+let tokenwrap (_,info,_,_) s ast = wrap ast info.Ast.line no_isos
+let iso_tokenwrap (_,info,_,_) s ast iso = wrap ast info.Ast.line iso
+
+let dots fn d =
+ rewrap d no_isos
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) -> Ast.DOTS(List.map fn x)
+ | Ast0.CIRCLES(x) -> Ast.CIRCLES(List.map fn x)
+ | Ast0.STARS(x) -> Ast.STARS(List.map fn x))
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let rec do_isos l = List.map (function (nm,x) -> (nm,anything x)) l
+
+and ident i =
+ rewrap i (do_isos (Ast0.get_iso i))
+ (match Ast0.unwrap i with
+ Ast0.Id(name) -> Ast.Id(mcode name)
+ | Ast0.MetaId(name,constraints,_) ->
+ let constraints = List.map ident constraints in
+ Ast.MetaId(mcode name,constraints,unitary,false)
+ | Ast0.MetaFunc(name,constraints,_) ->
+ let constraints = List.map ident constraints in
+ Ast.MetaFunc(mcode name,constraints,unitary,false)
+ | Ast0.MetaLocalFunc(name,constraints,_) ->
+ let constraints = List.map ident constraints in
+ Ast.MetaLocalFunc(mcode name,constraints,unitary,false)
+ | Ast0.OptIdent(id) -> Ast.OptIdent(ident id)
+ | Ast0.UniqueIdent(id) -> Ast.UniqueIdent(ident id))
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+and expression e =
+ let e1 =
+ rewrap e (do_isos (Ast0.get_iso e))
+ (match Ast0.unwrap e with
+ Ast0.Ident(id) -> Ast.Ident(ident id)
+ | Ast0.Constant(const) ->
+ Ast.Constant(mcode const)
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ let fn = expression fn in
+ let lp = mcode lp in
+ let args = dots expression args in
+ let rp = mcode rp in
+ Ast.FunCall(fn,lp,args,rp)
+ | Ast0.Assignment(left,op,right,simple) ->
+ Ast.Assignment(expression left,mcode op,expression right,simple)
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ let exp1 = expression exp1 in
+ let why = mcode why in
+ let exp2 = get_option expression exp2 in
+ let colon = mcode colon in
+ let exp3 = expression exp3 in
+ Ast.CondExpr(exp1,why,exp2,colon,exp3)
+ | Ast0.Postfix(exp,op) ->
+ Ast.Postfix(expression exp,mcode op)
+ | Ast0.Infix(exp,op) ->
+ Ast.Infix(expression exp,mcode op)
+ | Ast0.Unary(exp,op) ->
+ Ast.Unary(expression exp,mcode op)
+ | Ast0.Binary(left,op,right) ->
+ Ast.Binary(expression left,mcode op,expression right)
+ | Ast0.Nested(left,op,right) ->
+ Ast.Nested(expression left,mcode op,expression right)
+ | Ast0.Paren(lp,exp,rp) ->
+ Ast.Paren(mcode lp,expression exp,mcode rp)
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ Ast.ArrayAccess(expression exp1,mcode lb,expression exp2,mcode rb)
+ | Ast0.RecordAccess(exp,pt,field) ->
+ Ast.RecordAccess(expression exp,mcode pt,ident field)
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ Ast.RecordPtAccess(expression exp,mcode ar,ident field)
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ Ast.Cast(mcode lp,typeC ty,mcode rp,expression exp)
+ | Ast0.SizeOfExpr(szf,exp) ->
+ Ast.SizeOfExpr(mcode szf,expression exp)
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ Ast.SizeOfType(mcode szf, mcode lp,typeC ty,mcode rp)
+ | Ast0.TypeExp(ty) -> Ast.TypeExp(typeC ty)
+ | Ast0.MetaErr(name,constraints,_) ->
+ let constraints = List.map expression constraints in
+ Ast.MetaErr(mcode name,constraints,unitary,false)
+ | Ast0.MetaExpr(name,constraints,ty,form,_) ->
+ let constraints = List.map expression constraints in
+ Ast.MetaExpr(mcode name,constraints,unitary,ty,form,false)
+ | Ast0.MetaExprList(name,Some lenname,_) ->
+ Ast.MetaExprList(mcode name,Some (mcode lenname,unitary,false),
+ unitary,false)
+ | Ast0.MetaExprList(name,None,_) ->
+ Ast.MetaExprList(mcode name,None,unitary,false)
+ | Ast0.EComma(cm) -> Ast.EComma(mcode cm)
+ | Ast0.DisjExpr(_,exps,_,_) -> Ast.DisjExpr(List.map expression exps)
+ | Ast0.NestExpr(_,exp_dots,_,whencode,multi) ->
+ let whencode = get_option expression whencode in
+ Ast.NestExpr(dots expression exp_dots,whencode,multi)
+ | Ast0.Edots(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option expression whencode in
+ Ast.Edots(dots,whencode)
+ | Ast0.Ecircles(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option expression whencode in
+ Ast.Ecircles(dots,whencode)
+ | Ast0.Estars(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option expression whencode in
+ Ast.Estars(dots,whencode)
+ | Ast0.OptExp(exp) -> Ast.OptExp(expression exp)
+ | Ast0.UniqueExp(exp) -> Ast.UniqueExp(expression exp)) in
+ if Ast0.get_test_exp e then Ast.set_test_exp e1 else e1
+
+and expression_dots ed = dots expression ed
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and typeC t =
+ rewrap t (do_isos (Ast0.get_iso t))
+ (match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) ->
+ let rec collect_disjs t =
+ match Ast0.unwrap t with
+ Ast0.DisjType(_,types,_,_) ->
+ if Ast0.get_iso t = []
+ then List.concat (List.map collect_disjs types)
+ else failwith "unexpected iso on a disjtype"
+ | _ -> [t] in
+ let res =
+ List.map
+ (function ty ->
+ Ast.Type
+ (Some (mcode cv),
+ rewrap ty (do_isos (Ast0.get_iso ty)) (base_typeC ty)))
+ (collect_disjs ty) in
+ (* one could worry that isos are lost because we flatten the
+ disjunctions. but there should not be isos on the disjunctions
+ themselves. *)
+ (match res with
+ [ty] -> ty
+ | types -> Ast.DisjType(List.map (rewrap t no_isos) types))
+ | Ast0.BaseType(_,_) | Ast0.ImplicitInt(_) | Ast0.Pointer(_,_)
+ | Ast0.FunctionPointer(_,_,_,_,_,_,_) | Ast0.FunctionType(_,_,_,_)
+ | Ast0.Array(_,_,_,_) | Ast0.StructUnionName(_,_)
+ | Ast0.StructUnionDef(_,_,_,_) | Ast0.TypeName(_) | Ast0.MetaType(_,_) ->
+ Ast.Type(None,rewrap t no_isos (base_typeC t))
+ | Ast0.DisjType(_,types,_,_) -> Ast.DisjType(List.map typeC types)
+ | Ast0.OptType(ty) -> Ast.OptType(typeC ty)
+ | Ast0.UniqueType(ty) -> Ast.UniqueType(typeC ty))
+
+and base_typeC t =
+ match Ast0.unwrap t with
+ Ast0.BaseType(ty,sign) ->
+ Ast.BaseType(mcode ty,get_option mcode sign)
+ | Ast0.ImplicitInt(sgn) -> Ast.ImplicitInt(mcode sgn)
+ | Ast0.Pointer(ty,star) -> Ast.Pointer(typeC ty,mcode star)
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ Ast.FunctionPointer
+ (typeC ty,mcode lp1,mcode star,mcode rp1,
+ mcode lp2,parameter_list params,mcode rp2)
+ | Ast0.FunctionType(ret,lp,params,rp) ->
+ let allminus = check_allminus.V0.combiner_typeC t in
+ Ast.FunctionType
+ (allminus,get_option typeC ret,mcode lp,
+ parameter_list params,mcode rp)
+ | Ast0.Array(ty,lb,size,rb) ->
+ Ast.Array(typeC ty,mcode lb,get_option expression size,mcode rb)
+ | Ast0.StructUnionName(kind,name) ->
+ Ast.StructUnionName(mcode kind,get_option ident name)
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ Ast.StructUnionDef(typeC ty,mcode lb,
+ dots declaration decls,
+ mcode rb)
+ | Ast0.TypeName(name) -> Ast.TypeName(mcode name)
+ | Ast0.MetaType(name,_) ->
+ Ast.MetaType(mcode name,unitary,false)
+ | _ -> failwith "ast0toast: unexpected type"
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and declaration d =
+ rewrap d (do_isos (Ast0.get_iso d))
+ (match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ let stg = get_option mcode stg in
+ let ty = typeC ty in
+ let id = ident id in
+ let eq = mcode eq in
+ let ini = initialiser ini in
+ let sem = mcode sem in
+ Ast.Init(stg,ty,id,eq,ini,sem)
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ (match Ast0.unwrap ty with
+ Ast0.FunctionType(tyx,lp1,params,rp1) ->
+ let allminus = check_allminus.V0.combiner_declaration d in
+ Ast.UnInit(get_option mcode stg,
+ rewrap ty (do_isos (Ast0.get_iso ty))
+ (Ast.Type
+ (None,
+ rewrap ty no_isos
+ (Ast.FunctionType
+ (allminus,get_option typeC tyx,mcode lp1,
+ parameter_list params,mcode rp1)))),
+ ident id,mcode sem)
+ | _ -> Ast.UnInit(get_option mcode stg,typeC ty,ident id,mcode sem))
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ let name = ident name in
+ let lp = mcode lp in
+ let args = dots expression args in
+ let rp = mcode rp in
+ let sem = mcode sem in
+ Ast.MacroDecl(name,lp,args,rp,sem)
+ | Ast0.TyDecl(ty,sem) -> Ast.TyDecl(typeC ty,mcode sem)
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ let id = typeC id in
+ (match Ast.unwrap id with
+ Ast.Type(None,id) -> (* only MetaType or Id *)
+ Ast.Typedef(mcode stg,typeC ty,id,mcode sem)
+ | _ -> failwith "bad typedef")
+ | Ast0.DisjDecl(_,decls,_,_) -> Ast.DisjDecl(List.map declaration decls)
+ | Ast0.Ddots(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option declaration whencode in
+ Ast.Ddots(dots,whencode)
+ | Ast0.OptDecl(decl) -> Ast.OptDecl(declaration decl)
+ | Ast0.UniqueDecl(decl) -> Ast.UniqueDecl(declaration decl))
+
+and declaration_dots l = dots declaration l
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and strip_idots initlist =
+ match Ast0.unwrap initlist with
+ Ast0.DOTS(x) ->
+ let (whencode,init) =
+ List.fold_left
+ (function (prevwhen,previnit) ->
+ function cur ->
+ match Ast0.unwrap cur with
+ Ast0.Idots(dots,Some whencode) ->
+ (whencode :: prevwhen, previnit)
+ | Ast0.Idots(dots,None) -> (prevwhen,previnit)
+ | _ -> (prevwhen, cur :: previnit))
+ ([],[]) x in
+ (List.rev whencode, List.rev init)
+ | Ast0.CIRCLES(x) | Ast0.STARS(x) -> failwith "not possible for an initlist"
+
+and initialiser i =
+ rewrap i no_isos
+ (match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> Ast.InitExpr(expression exp)
+ | Ast0.InitList(lb,initlist,rb) ->
+ let (whencode,initlist) = strip_idots initlist in
+ Ast.InitList(mcode lb,List.map initialiser initlist,mcode rb,
+ List.map initialiser whencode)
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ Ast.InitGccDotName(mcode dot,ident name,mcode eq,initialiser ini)
+ | Ast0.InitGccName(name,eq,ini) ->
+ Ast.InitGccName(ident name,mcode eq,initialiser ini)
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ Ast.InitGccIndex(mcode lb,expression exp,mcode rb,mcode eq,
+ initialiser ini)
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ Ast.InitGccRange(mcode lb,expression exp1,mcode dots,
+ expression exp2,mcode rb,mcode eq,initialiser ini)
+ | Ast0.IComma(comma) -> Ast.IComma(mcode comma)
+ | Ast0.Idots(_,_) -> failwith "Idots should have been removed"
+ | Ast0.OptIni(ini) -> Ast.OptIni(initialiser ini)
+ | Ast0.UniqueIni(ini) -> Ast.UniqueIni(initialiser ini))
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef p =
+ rewrap p no_isos
+ (match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> Ast.VoidParam(typeC ty)
+ | Ast0.Param(ty,id) -> Ast.Param(typeC ty,get_option ident id)
+ | Ast0.MetaParam(name,_) ->
+ Ast.MetaParam(mcode name,unitary,false)
+ | Ast0.MetaParamList(name,Some lenname,_) ->
+ Ast.MetaParamList(mcode name,Some(mcode lenname,unitary,false),
+ unitary,false)
+ | Ast0.MetaParamList(name,None,_) ->
+ Ast.MetaParamList(mcode name,None,unitary,false)
+ | Ast0.PComma(cm) -> Ast.PComma(mcode cm)
+ | Ast0.Pdots(dots) -> Ast.Pdots(mcode dots)
+ | Ast0.Pcircles(dots) -> Ast.Pcircles(mcode dots)
+ | Ast0.OptParam(param) -> Ast.OptParam(parameterTypeDef param)
+ | Ast0.UniqueParam(param) -> Ast.UniqueParam(parameterTypeDef param))
+
+and parameter_list l = dots parameterTypeDef l
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and statement s =
+ let rec statement seqible s =
+ let rewrap_stmt ast0 ast =
+ let befaft =
+ match Ast0.get_dots_bef_aft s with
+ Ast0.NoDots -> Ast.NoDots
+ | Ast0.DroppingBetweenDots s ->
+ Ast.DroppingBetweenDots (statement seqible s,get_ctr())
+ | Ast0.AddingBetweenDots s ->
+ Ast.AddingBetweenDots (statement seqible s,get_ctr()) in
+ Ast.set_dots_bef_aft befaft (rewrap ast0 no_isos ast) in
+ let rewrap_rule_elem ast0 ast =
+ rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
+ rewrap_stmt s
+ (match Ast0.unwrap s with
+ Ast0.Decl((_,bef),decl) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.Decl(convert_mcodekind bef,
+ check_allminus.V0.combiner_statement s,
+ declaration decl)))
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ let lbrace = mcode lbrace in
+ let (decls,body) = separate_decls seqible body in
+ let rbrace = mcode rbrace in
+ Ast.Seq(iso_tokenwrap lbrace s (Ast.SeqStart(lbrace))
+ (do_isos (Ast0.get_iso s)),
+ decls,body,
+ tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
+ | Ast0.ExprStatement(exp,sem) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.ExprStatement(expression exp,mcode sem)))
+ | Ast0.IfThen(iff,lp,exp,rp,branch,(_,aft)) ->
+ Ast.IfThen
+ (rewrap_rule_elem s
+ (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
+ statement Ast.NotSequencible branch,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(_,aft)) ->
+ let els = mcode els in
+ Ast.IfThenElse
+ (rewrap_rule_elem s
+ (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
+ statement Ast.NotSequencible branch1,
+ tokenwrap els s (Ast.Else(els)),
+ statement Ast.NotSequencible branch2,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.While(wh,lp,exp,rp,body,(_,aft)) ->
+ Ast.While(rewrap_rule_elem s
+ (Ast.WhileHeader
+ (mcode wh,mcode lp,expression exp,mcode rp)),
+ statement Ast.NotSequencible body,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
+ let wh = mcode wh in
+ Ast.Do(rewrap_rule_elem s (Ast.DoHeader(mcode d)),
+ statement Ast.NotSequencible body,
+ tokenwrap wh s
+ (Ast.WhileTail(wh,mcode lp,expression exp,mcode rp,
+ mcode sem)))
+ | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,(_,aft)) ->
+ let fr = mcode fr in
+ let lp = mcode lp in
+ let exp1 = get_option expression exp1 in
+ let sem1 = mcode sem1 in
+ let exp2 = get_option expression exp2 in
+ let sem2= mcode sem2 in
+ let exp3 = get_option expression exp3 in
+ let rp = mcode rp in
+ let body = statement Ast.NotSequencible body in
+ Ast.For(rewrap_rule_elem s
+ (Ast.ForHeader(fr,lp,exp1,sem1,exp2,sem2,exp3,rp)),
+ body,([],[],[],convert_mcodekind aft))
+ | Ast0.Iterator(nm,lp,args,rp,body,(_,aft)) ->
+ Ast.Iterator(rewrap_rule_elem s
+ (Ast.IteratorHeader
+ (ident nm,mcode lp,
+ dots expression args,
+ mcode rp)),
+ statement Ast.NotSequencible body,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ let switch = mcode switch in
+ let lp = mcode lp in
+ let exp = expression exp in
+ let rp = mcode rp in
+ let lb = mcode lb in
+ let cases = List.map case_line (Ast0.undots cases) in
+ let rb = mcode rb in
+ Ast.Switch(rewrap_rule_elem s (Ast.SwitchHeader(switch,lp,exp,rp)),
+ tokenwrap lb s (Ast.SeqStart(lb)),
+ cases,
+ tokenwrap rb s (Ast.SeqEnd(rb)))
+ | Ast0.Break(br,sem) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Break(mcode br,mcode sem)))
+ | Ast0.Continue(cont,sem) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Continue(mcode cont,mcode sem)))
+ | Ast0.Label(l,dd) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Label(ident l,mcode dd)))
+ | Ast0.Goto(goto,l,sem) ->
+ Ast.Atomic
+ (rewrap_rule_elem s (Ast.Goto(mcode goto,ident l,mcode sem)))
+ | Ast0.Return(ret,sem) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Return(mcode ret,mcode sem)))
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ Ast.Atomic
+ (rewrap_rule_elem s
+ (Ast.ReturnExpr(mcode ret,expression exp,mcode sem)))
+ | Ast0.MetaStmt(name,_) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.MetaStmt(mcode name,unitary,seqible,false)))
+ | Ast0.MetaStmtList(name,_) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.MetaStmtList(mcode name,unitary,false)))
+ | Ast0.TopExp(exp) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.TopExp(expression exp)))
+ | Ast0.Exp(exp) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Exp(expression exp)))
+ | Ast0.Ty(ty) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Ty(typeC ty)))
+ | Ast0.Disj(_,rule_elem_dots_list,_,_) ->
+ Ast.Disj(List.map (function x -> statement_dots seqible x)
+ rule_elem_dots_list)
+ | Ast0.Nest(_,rule_elem_dots,_,whn,multi) ->
+ Ast.Nest
+ (statement_dots Ast.Sequencible rule_elem_dots,
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn,
+ multi,[],[])
+ | Ast0.Dots(d,whn) ->
+ let d = mcode d in
+ let whn =
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn in
+ Ast.Dots(d,whn,[],[])
+ | Ast0.Circles(d,whn) ->
+ let d = mcode d in
+ let whn =
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn in
+ Ast.Circles(d,whn,[],[])
+ | Ast0.Stars(d,whn) ->
+ let d = mcode d in
+ let whn =
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn in
+ Ast.Stars(d,whn,[],[])
+ | Ast0.FunDecl((_,bef),fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ let fi = List.map fninfo fi in
+ let name = ident name in
+ let lp = mcode lp in
+ let params = parameter_list params in
+ let rp = mcode rp in
+ let lbrace = mcode lbrace in
+ let (decls,body) = separate_decls seqible body in
+ let rbrace = mcode rbrace in
+ let allminus = check_allminus.V0.combiner_statement s in
+ Ast.FunDecl(rewrap_rule_elem s
+ (Ast.FunHeader(convert_mcodekind bef,
+ allminus,fi,name,lp,params,rp)),
+ tokenwrap lbrace s (Ast.SeqStart(lbrace)),
+ decls,body,
+ tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
+ | Ast0.Include(inc,str) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Include(mcode inc,mcode str)))
+ | Ast0.Define(def,id,params,body) ->
+ Ast.Define
+ (rewrap_rule_elem s
+ (Ast.DefineHeader
+ (mcode def,ident id, define_parameters params)),
+ statement_dots Ast.NotSequencible (*not sure*) body)
+ | Ast0.OptStm(stm) -> Ast.OptStm(statement seqible stm)
+ | Ast0.UniqueStm(stm) -> Ast.UniqueStm(statement seqible stm))
+
+ and define_parameters p =
+ rewrap p no_isos
+ (match Ast0.unwrap p with
+ Ast0.NoParams -> Ast.NoParams
+ | Ast0.DParams(lp,params,rp) ->
+ Ast.DParams(mcode lp,
+ dots define_param params,
+ mcode rp))
+
+ and define_param p =
+ rewrap p no_isos
+ (match Ast0.unwrap p with
+ Ast0.DParam(id) -> Ast.DParam(ident id)
+ | Ast0.DPComma(comma) -> Ast.DPComma(mcode comma)
+ | Ast0.DPdots(d) -> Ast.DPdots(mcode d)
+ | Ast0.DPcircles(c) -> Ast.DPcircles(mcode c)
+ | Ast0.OptDParam(dp) -> Ast.OptDParam(define_param dp)
+ | Ast0.UniqueDParam(dp) -> Ast.UniqueDParam(define_param dp))
+
+ and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> Ast.WhenNot (notfn a)
+ | Ast0.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
+ | Ast0.WhenModifier(x) -> Ast.WhenModifier(x)
+
+ and process_list seqible isos = function
+ [] -> []
+ | x::rest ->
+ let first = statement seqible x in
+ let first =
+ if !Flag.track_iso_usage
+ then Ast.set_isos first (isos@(Ast.get_isos first))
+ else first in
+ (match Ast0.unwrap x with
+ Ast0.Dots(_,_) | Ast0.Nest(_) ->
+ first::(process_list (Ast.SequencibleAfterDots []) no_isos rest)
+ | _ ->
+ first::(process_list Ast.Sequencible no_isos rest))
+
+ and statement_dots seqible d =
+ let isos = do_isos (Ast0.get_iso d) in
+ rewrap d no_isos
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) -> Ast.DOTS(process_list seqible isos x)
+ | Ast0.CIRCLES(x) -> Ast.CIRCLES(process_list seqible isos x)
+ | Ast0.STARS(x) -> Ast.STARS(process_list seqible isos x))
+
+ and separate_decls seqible d =
+ let rec collect_decls = function
+ [] -> ([],[])
+ | (x::xs) as l ->
+ (match Ast0.unwrap x with
+ Ast0.Decl(_) ->
+ let (decls,other) = collect_decls xs in
+ (x :: decls,other)
+ | Ast0.Dots(_,_) | Ast0.Nest(_,_,_,_,_) ->
+ let (decls,other) = collect_decls xs in
+ (match decls with
+ [] -> ([],x::other)
+ | _ -> (x :: decls,other))
+ | Ast0.Disj(starter,stmt_dots_list,mids,ender) ->
+ let disjs = List.map collect_dot_decls stmt_dots_list in
+ let all_decls = List.for_all (function (_,s) -> s=[]) disjs in
+ if all_decls
+ then
+ let (decls,other) = collect_decls xs in
+ (x :: decls,other)
+ else ([],l)
+ | _ -> ([],l))
+
+ and collect_dot_decls d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> collect_decls x
+ | Ast0.CIRCLES(x) -> collect_decls x
+ | Ast0.STARS(x) -> collect_decls x in
+
+ let process l d fn =
+ let (decls,other) = collect_decls l in
+ (rewrap d no_isos (fn (List.map (statement seqible) decls)),
+ rewrap d no_isos
+ (fn (process_list seqible (do_isos (Ast0.get_iso d)) other))) in
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> process x d (function x -> Ast.DOTS x)
+ | Ast0.CIRCLES(x) -> process x d (function x -> Ast.CIRCLES x)
+ | Ast0.STARS(x) -> process x d (function x -> Ast.STARS x) in
+
+ statement Ast.Sequencible s
+
+and fninfo = function
+ Ast0.FStorage(stg) -> Ast.FStorage(mcode stg)
+ | Ast0.FType(ty) -> Ast.FType(typeC ty)
+ | Ast0.FInline(inline) -> Ast.FInline(mcode inline)
+ | Ast0.FAttr(attr) -> Ast.FAttr(mcode attr)
+
+and option_to_list = function
+ Some x -> [x]
+ | None -> []
+
+and case_line c =
+ rewrap c no_isos
+ (match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ let def = mcode def in
+ let colon = mcode colon in
+ let code = dots statement code in
+ Ast.CaseLine(rewrap c no_isos (Ast.Default(def,colon)),code)
+ | Ast0.Case(case,exp,colon,code) ->
+ let case = mcode case in
+ let exp = expression exp in
+ let colon = mcode colon in
+ let code = dots statement code in
+ Ast.CaseLine(rewrap c no_isos (Ast.Case(case,exp,colon)),code)
+ | Ast0.OptCase(case) -> Ast.OptCase(case_line case))
+
+and statement_dots l = dots statement l
+
+(* --------------------------------------------------------------------- *)
+
+(* what is possible is only what is at the top level in an iso *)
+and anything = function
+ Ast0.DotsExprTag(d) -> Ast.ExprDotsTag(expression_dots d)
+ | Ast0.DotsParamTag(d) -> Ast.ParamDotsTag(parameter_list d)
+ | Ast0.DotsInitTag(d) -> failwith "not possible"
+ | Ast0.DotsStmtTag(d) -> Ast.StmtDotsTag(statement_dots d)
+ | Ast0.DotsDeclTag(d) -> Ast.DeclDotsTag(declaration_dots d)
+ | Ast0.DotsCaseTag(d) -> failwith "not possible"
+ | Ast0.IdentTag(d) -> Ast.IdentTag(ident d)
+ | Ast0.ExprTag(d) -> Ast.ExpressionTag(expression d)
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "only in isos, not converted to ast"
+ | Ast0.TypeCTag(d) -> Ast.FullTypeTag(typeC d)
+ | Ast0.ParamTag(d) -> Ast.ParamTag(parameterTypeDef d)
+ | Ast0.InitTag(d) -> Ast.InitTag(initialiser d)
+ | Ast0.DeclTag(d) -> Ast.DeclarationTag(declaration d)
+ | Ast0.StmtTag(d) -> Ast.StatementTag(statement d)
+ | Ast0.CaseLineTag(d) -> Ast.CaseLineTag(case_line d)
+ | Ast0.TopTag(d) -> Ast.Code(top_level d)
+ | Ast0.IsoWhenTag(_) -> failwith "not possible"
+ | Ast0.MetaPosTag _ -> failwith "not possible"
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+(* top level isos are probably lost to tracking *)
+
+and top_level t =
+ rewrap t no_isos
+ (match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ Ast.FILEINFO(mcode old_file,mcode new_file)
+ | Ast0.DECL(stmt) -> Ast.DECL(statement stmt)
+ | Ast0.CODE(rule_elem_dots) ->
+ Ast.CODE(statement_dots rule_elem_dots)
+ | Ast0.ERRORWORDS(exps) -> Ast.ERRORWORDS(List.map expression exps)
+ | Ast0.OTHER(_) -> failwith "eliminated by top_level")
+
+(* --------------------------------------------------------------------- *)
+(* Entry point for minus code *)
+
+(* Inline_mcodes is very important - sends + code attached to the - code
+down to the mcodes. The functions above can only be used when there is no
+attached + code, eg in + code itself. *)
+let ast0toast_toplevel x =
+ inline_mcodes.V0.combiner_top_level x;
+ top_level x
+
+let ast0toast name deps dropped exists x is_exp =
+ List.iter inline_mcodes.V0.combiner_top_level x;
+ Ast.CocciRule (name,(deps,dropped,exists),List.map top_level x,is_exp)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Arities matter for the minus slice, but not for the plus slice. *)
+
+(* + only allowed on code in a nest (in_nest = true). ? only allowed on
+rule_elems, and on subterms if the context is ? also. *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module V0 = Visitor_ast0
+module V = Visitor_ast
+
+let unitary = Type_cocci.Unitary
+
+let ctr = ref 0
+let get_ctr _ =
+ let c = !ctr in
+ ctr := !ctr + 1;
+ c
+
+(* --------------------------------------------------------------------- *)
+(* Move plus tokens from the MINUS and CONTEXT structured nodes to the
+corresponding leftmost and rightmost mcodes *)
+
+let inline_mcodes =
+ let bind x y = () in
+ let option_default = () in
+ let mcode _ = () in
+ let do_nothing r k e =
+ k e;
+ let einfo = Ast0.get_info e in
+ match (Ast0.get_mcodekind e) with
+ Ast0.MINUS(replacements) ->
+ (match !replacements with
+ ([],_) -> ()
+ | replacements ->
+ let minus_try = function
+ (true,mc) ->
+ if List.for_all
+ (function
+ Ast0.MINUS(mreplacements) -> true | _ -> false)
+ mc
+ then
+ (List.iter
+ (function
+ Ast0.MINUS(mreplacements) ->
+ mreplacements := replacements
+ | _ -> ())
+ mc;
+ true)
+ else false
+ | _ -> false in
+ if not (minus_try(einfo.Ast0.attachable_start,
+ einfo.Ast0.mcode_start)
+ or
+ minus_try(einfo.Ast0.attachable_end,
+ einfo.Ast0.mcode_end))
+ then
+ failwith "minus tree should not have bad code on both sides")
+ | Ast0.CONTEXT(befaft)
+ | Ast0.MIXED(befaft) ->
+ let concat starter startinfo ender endinfo =
+ let lst =
+ match (starter,ender) with
+ ([],_) -> ender
+ | (_,[]) -> starter
+ | _ ->
+ if startinfo.Ast0.tline_end = endinfo.Ast0.tline_start
+ then (* put them in the same inner list *)
+ let last = List.hd (List.rev starter) in
+ let butlast = List.rev(List.tl(List.rev starter)) in
+ butlast @ (last@(List.hd ender)) :: (List.tl ender)
+ else starter @ ender in
+ (lst,
+ {endinfo with Ast0.tline_start = startinfo.Ast0.tline_start}) in
+ let attach_bef bef beforeinfo = function
+ (true,mcl) ->
+ List.iter
+ (function
+ Ast0.MINUS(mreplacements) ->
+ let (mrepl,tokeninfo) = !mreplacements in
+ mreplacements := concat bef beforeinfo mrepl tokeninfo
+ | Ast0.CONTEXT(mbefaft) ->
+ (match !mbefaft with
+ (Ast.BEFORE(mbef),mbeforeinfo,a) ->
+ let (newbef,newinfo) =
+ concat bef beforeinfo mbef mbeforeinfo in
+ mbefaft := (Ast.BEFORE(newbef),newinfo,a)
+ | (Ast.AFTER(maft),_,a) ->
+ mbefaft :=
+ (Ast.BEFOREAFTER(bef,maft),beforeinfo,a)
+ | (Ast.BEFOREAFTER(mbef,maft),mbeforeinfo,a) ->
+ let (newbef,newinfo) =
+ concat bef beforeinfo mbef mbeforeinfo in
+ mbefaft :=
+ (Ast.BEFOREAFTER(newbef,maft),newinfo,a)
+ | (Ast.NOTHING,_,a) ->
+ mbefaft := (Ast.BEFORE(bef),beforeinfo,a))
+ | _ -> failwith "unexpected annotation")
+ mcl
+ | _ ->
+ failwith
+ "context tree should not have bad code on both sides" in
+ let attach_aft aft afterinfo = function
+ (true,mcl) ->
+ List.iter
+ (function
+ Ast0.MINUS(mreplacements) ->
+ let (mrepl,tokeninfo) = !mreplacements in
+ mreplacements := concat mrepl tokeninfo aft afterinfo
+ | Ast0.CONTEXT(mbefaft) ->
+ (match !mbefaft with
+ (Ast.BEFORE(mbef),b,_) ->
+ mbefaft :=
+ (Ast.BEFOREAFTER(mbef,aft),b,afterinfo)
+ | (Ast.AFTER(maft),b,mafterinfo) ->
+ let (newaft,newinfo) =
+ concat maft mafterinfo aft afterinfo in
+ mbefaft := (Ast.AFTER(newaft),b,newinfo)
+ | (Ast.BEFOREAFTER(mbef,maft),b,mafterinfo) ->
+ let (newaft,newinfo) =
+ concat maft mafterinfo aft afterinfo in
+ mbefaft :=
+ (Ast.BEFOREAFTER(mbef,newaft),b,newinfo)
+ | (Ast.NOTHING,b,_) ->
+ mbefaft := (Ast.AFTER(aft),b,afterinfo))
+ | _ -> failwith "unexpected annotation")
+ mcl
+ | _ ->
+ failwith
+ "context tree should not have bad code on both sides" in
+ (match !befaft with
+ (Ast.BEFORE(bef),beforeinfo,_) ->
+ attach_bef bef beforeinfo
+ (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start)
+ | (Ast.AFTER(aft),_,afterinfo) ->
+ attach_aft aft afterinfo
+ (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
+ | (Ast.BEFOREAFTER(bef,aft),beforeinfo,afterinfo) ->
+ attach_bef bef beforeinfo
+ (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start);
+ attach_aft aft afterinfo
+ (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
+ | (Ast.NOTHING,_,_) -> ())
+ | Ast0.PLUS -> () in
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode mcode mcode
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing
+
+(* --------------------------------------------------------------------- *)
+(* For function declarations. Can't use the mcode at the root, because that
+might be mixed when the function contains ()s, where agglomeration of -s is
+not possible. *)
+
+let check_allminus =
+ let donothing r k e = k e in
+ let bind x y = x && y in
+ let option_default = true in
+ let mcode (_,_,_,mc,_) =
+ match mc with
+ Ast0.MINUS(r) -> let (plusses,_) = !r in plusses = []
+ | _ -> false in
+
+ (* special case for disj *)
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ List.for_all r.V0.combiner_expression expr_list
+ | _ -> k e in
+
+ let declaration r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjDecl(starter,decls,mids,ender) ->
+ List.for_all r.V0.combiner_declaration decls
+ | _ -> k e in
+
+ let typeC r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjType(starter,decls,mids,ender) ->
+ List.for_all r.V0.combiner_typeC decls
+ | _ -> k e in
+
+ let statement r k e =
+ match Ast0.unwrap e with
+ Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ List.for_all r.V0.combiner_statement_dots statement_dots_list
+ | _ -> k e in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode mcode mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing expression typeC donothing donothing declaration
+ statement donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+
+let get_option fn = function
+ None -> None
+ | Some x -> Some (fn x)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Mcode *)
+
+let convert_info info =
+ { Ast.line = info.Ast0.line_start; Ast.column = info.Ast0.column;
+ Ast.strbef = info.Ast0.strings_before;
+ Ast.straft = info.Ast0.strings_after; }
+
+let convert_mcodekind = function
+ Ast0.MINUS(replacements) ->
+ let (replacements,_) = !replacements in
+ Ast.MINUS(Ast.NoPos,replacements)
+ | Ast0.PLUS -> Ast.PLUS
+ | Ast0.CONTEXT(befaft) ->
+ let (befaft,_,_) = !befaft in Ast.CONTEXT(Ast.NoPos,befaft)
+ | Ast0.MIXED(_) -> failwith "not possible for mcode"
+
+let pos_mcode(term,_,info,mcodekind,pos) =
+ (* avoids a recursion problem *)
+ (term,convert_info info,convert_mcodekind mcodekind,Ast.NoMetaPos)
+
+let mcode(term,_,info,mcodekind,pos) =
+ let pos =
+ match !pos with
+ Ast0.MetaPos(pos,constraints,per) ->
+ Ast.MetaPos(pos_mcode pos,constraints,per,unitary,false)
+ | _ -> Ast.NoMetaPos in
+ (term,convert_info info,convert_mcodekind mcodekind,pos)
+
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+let wrap ast line isos =
+ {(Ast.make_term ast) with Ast.node_line = line;
+ Ast.iso_info = isos}
+
+let rewrap ast0 isos ast =
+ wrap ast ((Ast0.get_info ast0).Ast0.line_start) isos
+
+let no_isos = []
+
+(* no isos on tokens *)
+let tokenwrap (_,info,_,_) s ast = wrap ast info.Ast.line no_isos
+let iso_tokenwrap (_,info,_,_) s ast iso = wrap ast info.Ast.line iso
+
+let dots fn d =
+ rewrap d no_isos
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) -> Ast.DOTS(List.map fn x)
+ | Ast0.CIRCLES(x) -> Ast.CIRCLES(List.map fn x)
+ | Ast0.STARS(x) -> Ast.STARS(List.map fn x))
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let rec do_isos l = List.map (function (nm,x) -> (nm,anything x)) l
+
+and ident i =
+ rewrap i (do_isos (Ast0.get_iso i))
+ (match Ast0.unwrap i with
+ Ast0.Id(name) -> Ast.Id(mcode name)
+ | Ast0.MetaId(name,constraints,_) ->
+ let constraints = List.map ident constraints in
+ Ast.MetaId(mcode name,constraints,unitary,false)
+ | Ast0.MetaFunc(name,constraints,_) ->
+ let constraints = List.map ident constraints in
+ Ast.MetaFunc(mcode name,constraints,unitary,false)
+ | Ast0.MetaLocalFunc(name,constraints,_) ->
+ let constraints = List.map ident constraints in
+ Ast.MetaLocalFunc(mcode name,constraints,unitary,false)
+ | Ast0.OptIdent(id) -> Ast.OptIdent(ident id)
+ | Ast0.UniqueIdent(id) -> Ast.UniqueIdent(ident id))
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+and expression e =
+ let e1 =
+ rewrap e (do_isos (Ast0.get_iso e))
+ (match Ast0.unwrap e with
+ Ast0.Ident(id) -> Ast.Ident(ident id)
+ | Ast0.Constant(const) ->
+ Ast.Constant(mcode const)
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ let fn = expression fn in
+ let lp = mcode lp in
+ let args = dots expression args in
+ let rp = mcode rp in
+ Ast.FunCall(fn,lp,args,rp)
+ | Ast0.Assignment(left,op,right,simple) ->
+ Ast.Assignment(expression left,mcode op,expression right,simple)
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ let exp1 = expression exp1 in
+ let why = mcode why in
+ let exp2 = get_option expression exp2 in
+ let colon = mcode colon in
+ let exp3 = expression exp3 in
+ Ast.CondExpr(exp1,why,exp2,colon,exp3)
+ | Ast0.Postfix(exp,op) ->
+ Ast.Postfix(expression exp,mcode op)
+ | Ast0.Infix(exp,op) ->
+ Ast.Infix(expression exp,mcode op)
+ | Ast0.Unary(exp,op) ->
+ Ast.Unary(expression exp,mcode op)
+ | Ast0.Binary(left,op,right) ->
+ Ast.Binary(expression left,mcode op,expression right)
+ | Ast0.Nested(left,op,right) ->
+ Ast.Nested(expression left,mcode op,expression right)
+ | Ast0.Paren(lp,exp,rp) ->
+ Ast.Paren(mcode lp,expression exp,mcode rp)
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ Ast.ArrayAccess(expression exp1,mcode lb,expression exp2,mcode rb)
+ | Ast0.RecordAccess(exp,pt,field) ->
+ Ast.RecordAccess(expression exp,mcode pt,ident field)
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ Ast.RecordPtAccess(expression exp,mcode ar,ident field)
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ Ast.Cast(mcode lp,typeC ty,mcode rp,expression exp)
+ | Ast0.SizeOfExpr(szf,exp) ->
+ Ast.SizeOfExpr(mcode szf,expression exp)
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ Ast.SizeOfType(mcode szf, mcode lp,typeC ty,mcode rp)
+ | Ast0.TypeExp(ty) -> Ast.TypeExp(typeC ty)
+ | Ast0.MetaErr(name,constraints,_) ->
+ let constraints = List.map expression constraints in
+ Ast.MetaErr(mcode name,constraints,unitary,false)
+ | Ast0.MetaExpr(name,constraints,ty,form,_) ->
+ let constraints = List.map expression constraints in
+ Ast.MetaExpr(mcode name,constraints,unitary,ty,form,false)
+ | Ast0.MetaExprList(name,Some lenname,_) ->
+ Ast.MetaExprList(mcode name,Some (mcode lenname,unitary,false),
+ unitary,false)
+ | Ast0.MetaExprList(name,None,_) ->
+ Ast.MetaExprList(mcode name,None,unitary,false)
+ | Ast0.EComma(cm) -> Ast.EComma(mcode cm)
+ | Ast0.DisjExpr(_,exps,_,_) -> Ast.DisjExpr(List.map expression exps)
+ | Ast0.NestExpr(_,exp_dots,_,whencode,multi) ->
+ let whencode = get_option expression whencode in
+ Ast.NestExpr(dots expression exp_dots,whencode,multi)
+ | Ast0.Edots(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option expression whencode in
+ Ast.Edots(dots,whencode)
+ | Ast0.Ecircles(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option expression whencode in
+ Ast.Ecircles(dots,whencode)
+ | Ast0.Estars(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option expression whencode in
+ Ast.Estars(dots,whencode)
+ | Ast0.OptExp(exp) -> Ast.OptExp(expression exp)
+ | Ast0.UniqueExp(exp) -> Ast.UniqueExp(expression exp)) in
+ if Ast0.get_test_exp e then Ast.set_test_exp e1 else e1
+
+and expression_dots ed = dots expression ed
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and typeC t =
+ rewrap t (do_isos (Ast0.get_iso t))
+ (match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) ->
+ let rec collect_disjs t =
+ match Ast0.unwrap t with
+ Ast0.DisjType(_,types,_,_) ->
+ if Ast0.get_iso t = []
+ then List.concat (List.map collect_disjs types)
+ else failwith "unexpected iso on a disjtype"
+ | _ -> [t] in
+ let res =
+ List.map
+ (function ty ->
+ Ast.Type
+ (Some (mcode cv),
+ rewrap ty (do_isos (Ast0.get_iso ty)) (base_typeC ty)))
+ (collect_disjs ty) in
+ (* one could worry that isos are lost because we flatten the
+ disjunctions. but there should not be isos on the disjunctions
+ themselves. *)
+ (match res with
+ [ty] -> ty
+ | types -> Ast.DisjType(List.map (rewrap t no_isos) types))
+ | Ast0.BaseType(_,_) | Ast0.ImplicitInt(_) | Ast0.Pointer(_,_)
+ | Ast0.FunctionPointer(_,_,_,_,_,_,_) | Ast0.FunctionType(_,_,_,_)
+ | Ast0.Array(_,_,_,_) | Ast0.StructUnionName(_,_)
+ | Ast0.StructUnionDef(_,_,_,_) | Ast0.TypeName(_) | Ast0.MetaType(_,_) ->
+ Ast.Type(None,rewrap t no_isos (base_typeC t))
+ | Ast0.DisjType(_,types,_,_) -> Ast.DisjType(List.map typeC types)
+ | Ast0.OptType(ty) -> Ast.OptType(typeC ty)
+ | Ast0.UniqueType(ty) -> Ast.UniqueType(typeC ty))
+
+and base_typeC t =
+ match Ast0.unwrap t with
+ Ast0.BaseType(ty,sign) ->
+ Ast.BaseType(mcode ty,get_option mcode sign)
+ | Ast0.ImplicitInt(sgn) -> Ast.ImplicitInt(mcode sgn)
+ | Ast0.Pointer(ty,star) -> Ast.Pointer(typeC ty,mcode star)
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ Ast.FunctionPointer
+ (typeC ty,mcode lp1,mcode star,mcode rp1,
+ mcode lp2,parameter_list params,mcode rp2)
+ | Ast0.FunctionType(ret,lp,params,rp) ->
+ let allminus = check_allminus.V0.combiner_typeC t in
+ Ast.FunctionType
+ (allminus,get_option typeC ret,mcode lp,
+ parameter_list params,mcode rp)
+ | Ast0.Array(ty,lb,size,rb) ->
+ Ast.Array(typeC ty,mcode lb,get_option expression size,mcode rb)
+ | Ast0.StructUnionName(kind,name) ->
+ Ast.StructUnionName(mcode kind,get_option ident name)
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ Ast.StructUnionDef(typeC ty,mcode lb,
+ dots declaration decls,
+ mcode rb)
+ | Ast0.TypeName(name) -> Ast.TypeName(mcode name)
+ | Ast0.MetaType(name,_) ->
+ Ast.MetaType(mcode name,unitary,false)
+ | _ -> failwith "ast0toast: unexpected type"
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and declaration d =
+ rewrap d (do_isos (Ast0.get_iso d))
+ (match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ let stg = get_option mcode stg in
+ let ty = typeC ty in
+ let id = ident id in
+ let eq = mcode eq in
+ let ini = initialiser ini in
+ let sem = mcode sem in
+ Ast.Init(stg,ty,id,eq,ini,sem)
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ (match Ast0.unwrap ty with
+ Ast0.FunctionType(tyx,lp1,params,rp1) ->
+ let allminus = check_allminus.V0.combiner_declaration d in
+ Ast.UnInit(get_option mcode stg,
+ rewrap ty (do_isos (Ast0.get_iso ty))
+ (Ast.Type
+ (None,
+ rewrap ty no_isos
+ (Ast.FunctionType
+ (allminus,get_option typeC tyx,mcode lp1,
+ parameter_list params,mcode rp1)))),
+ ident id,mcode sem)
+ | _ -> Ast.UnInit(get_option mcode stg,typeC ty,ident id,mcode sem))
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ let name = ident name in
+ let lp = mcode lp in
+ let args = dots expression args in
+ let rp = mcode rp in
+ let sem = mcode sem in
+ Ast.MacroDecl(name,lp,args,rp,sem)
+ | Ast0.TyDecl(ty,sem) -> Ast.TyDecl(typeC ty,mcode sem)
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ let id = typeC id in
+ (match Ast.unwrap id with
+ Ast.Type(None,id) -> (* only MetaType or Id *)
+ Ast.Typedef(mcode stg,typeC ty,id,mcode sem)
+ | _ -> failwith "bad typedef")
+ | Ast0.DisjDecl(_,decls,_,_) -> Ast.DisjDecl(List.map declaration decls)
+ | Ast0.Ddots(dots,whencode) ->
+ let dots = mcode dots in
+ let whencode = get_option declaration whencode in
+ Ast.Ddots(dots,whencode)
+ | Ast0.OptDecl(decl) -> Ast.OptDecl(declaration decl)
+ | Ast0.UniqueDecl(decl) -> Ast.UniqueDecl(declaration decl))
+
+and declaration_dots l = dots declaration l
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and strip_idots initlist =
+ match Ast0.unwrap initlist with
+ Ast0.DOTS(x) ->
+ let (whencode,init) =
+ List.fold_left
+ (function (prevwhen,previnit) ->
+ function cur ->
+ match Ast0.unwrap cur with
+ Ast0.Idots(dots,Some whencode) ->
+ (whencode :: prevwhen, previnit)
+ | Ast0.Idots(dots,None) -> (prevwhen,previnit)
+ | _ -> (prevwhen, cur :: previnit))
+ ([],[]) x in
+ (List.rev whencode, List.rev init)
+ | Ast0.CIRCLES(x) | Ast0.STARS(x) -> failwith "not possible for an initlist"
+
+and initialiser i =
+ rewrap i no_isos
+ (match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> Ast.InitExpr(expression exp)
+ | Ast0.InitList(lb,initlist,rb) ->
+ let (whencode,initlist) = strip_idots initlist in
+ Ast.InitList(mcode lb,List.map initialiser initlist,mcode rb,
+ List.map initialiser whencode)
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ Ast.InitGccDotName(mcode dot,ident name,mcode eq,initialiser ini)
+ | Ast0.InitGccName(name,eq,ini) ->
+ Ast.InitGccName(ident name,mcode eq,initialiser ini)
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ Ast.InitGccIndex(mcode lb,expression exp,mcode rb,mcode eq,
+ initialiser ini)
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ Ast.InitGccRange(mcode lb,expression exp1,mcode dots,
+ expression exp2,mcode rb,mcode eq,initialiser ini)
+ | Ast0.IComma(comma) -> Ast.IComma(mcode comma)
+ | Ast0.Idots(_,_) -> failwith "Idots should have been removed"
+ | Ast0.OptIni(ini) -> Ast.OptIni(initialiser ini)
+ | Ast0.UniqueIni(ini) -> Ast.UniqueIni(initialiser ini))
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef p =
+ rewrap p no_isos
+ (match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> Ast.VoidParam(typeC ty)
+ | Ast0.Param(ty,id) -> Ast.Param(typeC ty,get_option ident id)
+ | Ast0.MetaParam(name,_) ->
+ Ast.MetaParam(mcode name,unitary,false)
+ | Ast0.MetaParamList(name,Some lenname,_) ->
+ Ast.MetaParamList(mcode name,Some(mcode lenname,unitary,false),
+ unitary,false)
+ | Ast0.MetaParamList(name,None,_) ->
+ Ast.MetaParamList(mcode name,None,unitary,false)
+ | Ast0.PComma(cm) -> Ast.PComma(mcode cm)
+ | Ast0.Pdots(dots) -> Ast.Pdots(mcode dots)
+ | Ast0.Pcircles(dots) -> Ast.Pcircles(mcode dots)
+ | Ast0.OptParam(param) -> Ast.OptParam(parameterTypeDef param)
+ | Ast0.UniqueParam(param) -> Ast.UniqueParam(parameterTypeDef param))
+
+and parameter_list l = dots parameterTypeDef l
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and statement s =
+ let rec statement seqible s =
+ let rewrap_stmt ast0 ast =
+ let befaft =
+ match Ast0.get_dots_bef_aft s with
+ Ast0.NoDots -> Ast.NoDots
+ | Ast0.DroppingBetweenDots s ->
+ Ast.DroppingBetweenDots (statement seqible s,get_ctr())
+ | Ast0.AddingBetweenDots s ->
+ Ast.AddingBetweenDots (statement seqible s,get_ctr()) in
+ Ast.set_dots_bef_aft befaft (rewrap ast0 no_isos ast) in
+ let rewrap_rule_elem ast0 ast =
+ rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
+ rewrap_stmt s
+ (match Ast0.unwrap s with
+ Ast0.Decl((_,bef),decl) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.Decl(convert_mcodekind bef,
+ check_allminus.V0.combiner_statement s,
+ declaration decl)))
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ let lbrace = mcode lbrace in
+ let (decls,body) = separate_decls seqible body in
+ let rbrace = mcode rbrace in
+ Ast.Seq(iso_tokenwrap lbrace s (Ast.SeqStart(lbrace))
+ (do_isos (Ast0.get_iso s)),
+ decls,body,
+ tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
+ | Ast0.ExprStatement(exp,sem) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.ExprStatement(expression exp,mcode sem)))
+ | Ast0.IfThen(iff,lp,exp,rp,branch,(_,aft)) ->
+ Ast.IfThen
+ (rewrap_rule_elem s
+ (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
+ statement Ast.NotSequencible branch,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(_,aft)) ->
+ let els = mcode els in
+ Ast.IfThenElse
+ (rewrap_rule_elem s
+ (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
+ statement Ast.NotSequencible branch1,
+ tokenwrap els s (Ast.Else(els)),
+ statement Ast.NotSequencible branch2,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.While(wh,lp,exp,rp,body,(_,aft)) ->
+ Ast.While(rewrap_rule_elem s
+ (Ast.WhileHeader
+ (mcode wh,mcode lp,expression exp,mcode rp)),
+ statement Ast.NotSequencible body,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
+ let wh = mcode wh in
+ Ast.Do(rewrap_rule_elem s (Ast.DoHeader(mcode d)),
+ statement Ast.NotSequencible body,
+ tokenwrap wh s
+ (Ast.WhileTail(wh,mcode lp,expression exp,mcode rp,
+ mcode sem)))
+ | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,(_,aft)) ->
+ let fr = mcode fr in
+ let lp = mcode lp in
+ let exp1 = get_option expression exp1 in
+ let sem1 = mcode sem1 in
+ let exp2 = get_option expression exp2 in
+ let sem2= mcode sem2 in
+ let exp3 = get_option expression exp3 in
+ let rp = mcode rp in
+ let body = statement Ast.NotSequencible body in
+ Ast.For(rewrap_rule_elem s
+ (Ast.ForHeader(fr,lp,exp1,sem1,exp2,sem2,exp3,rp)),
+ body,([],[],[],convert_mcodekind aft))
+ | Ast0.Iterator(nm,lp,args,rp,body,(_,aft)) ->
+ Ast.Iterator(rewrap_rule_elem s
+ (Ast.IteratorHeader
+ (ident nm,mcode lp,
+ dots expression args,
+ mcode rp)),
+ statement Ast.NotSequencible body,
+ ([],[],[],convert_mcodekind aft))
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ let switch = mcode switch in
+ let lp = mcode lp in
+ let exp = expression exp in
+ let rp = mcode rp in
+ let lb = mcode lb in
+ let cases = List.map case_line (Ast0.undots cases) in
+ let rb = mcode rb in
+ Ast.Switch(rewrap_rule_elem s (Ast.SwitchHeader(switch,lp,exp,rp)),
+ tokenwrap lb s (Ast.SeqStart(lb)),
+ cases,
+ tokenwrap rb s (Ast.SeqEnd(rb)))
+ | Ast0.Break(br,sem) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Break(mcode br,mcode sem)))
+ | Ast0.Continue(cont,sem) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Continue(mcode cont,mcode sem)))
+ | Ast0.Label(l,dd) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Label(ident l,mcode dd)))
+ | Ast0.Goto(goto,l,sem) ->
+ Ast.Atomic
+ (rewrap_rule_elem s (Ast.Goto(mcode goto,ident l,mcode sem)))
+ | Ast0.Return(ret,sem) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Return(mcode ret,mcode sem)))
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ Ast.Atomic
+ (rewrap_rule_elem s
+ (Ast.ReturnExpr(mcode ret,expression exp,mcode sem)))
+ | Ast0.MetaStmt(name,_) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.MetaStmt(mcode name,unitary,seqible,false)))
+ | Ast0.MetaStmtList(name,_) ->
+ Ast.Atomic(rewrap_rule_elem s
+ (Ast.MetaStmtList(mcode name,unitary,false)))
+ | Ast0.TopExp(exp) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.TopExp(expression exp)))
+ | Ast0.Exp(exp) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Exp(expression exp)))
+ | Ast0.Ty(ty) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Ty(typeC ty)))
+ | Ast0.Disj(_,rule_elem_dots_list,_,_) ->
+ Ast.Disj(List.map (function x -> statement_dots seqible x)
+ rule_elem_dots_list)
+ | Ast0.Nest(_,rule_elem_dots,_,whn,multi) ->
+ Ast.Nest
+ (statement_dots Ast.Sequencible rule_elem_dots,
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn,
+ multi,[],[])
+ | Ast0.Dots(d,whn) ->
+ let d = mcode d in
+ let whn =
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn in
+ Ast.Dots(d,whn,[],[])
+ | Ast0.Circles(d,whn) ->
+ let d = mcode d in
+ let whn =
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn in
+ Ast.Circles(d,whn,[],[])
+ | Ast0.Stars(d,whn) ->
+ let d = mcode d in
+ let whn =
+ List.map
+ (whencode (statement_dots Ast.Sequencible)
+ (statement Ast.NotSequencible))
+ whn in
+ Ast.Stars(d,whn,[],[])
+ | Ast0.FunDecl((_,bef),fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ let fi = List.map fninfo fi in
+ let name = ident name in
+ let lp = mcode lp in
+ let params = parameter_list params in
+ let rp = mcode rp in
+ let lbrace = mcode lbrace in
+ let (decls,body) = separate_decls seqible body in
+ let rbrace = mcode rbrace in
+ let allminus = check_allminus.V0.combiner_statement s in
+ Ast.FunDecl(rewrap_rule_elem s
+ (Ast.FunHeader(convert_mcodekind bef,
+ allminus,fi,name,lp,params,rp)),
+ tokenwrap lbrace s (Ast.SeqStart(lbrace)),
+ decls,body,
+ tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
+ | Ast0.Include(inc,str) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.Include(mcode inc,mcode str)))
+ | Ast0.Define(def,id,params,body) ->
+ Ast.Define
+ (rewrap_rule_elem s
+ (Ast.DefineHeader
+ (mcode def,ident id, define_parameters params)),
+ statement_dots Ast.NotSequencible (*not sure*) body)
+ | Ast0.OptStm(stm) -> Ast.OptStm(statement seqible stm)
+ | Ast0.UniqueStm(stm) -> Ast.UniqueStm(statement seqible stm))
+
+ and define_parameters p =
+ rewrap p no_isos
+ (match Ast0.unwrap p with
+ Ast0.NoParams -> Ast.NoParams
+ | Ast0.DParams(lp,params,rp) ->
+ Ast.DParams(mcode lp,
+ dots define_param params,
+ mcode rp))
+
+ and define_param p =
+ rewrap p no_isos
+ (match Ast0.unwrap p with
+ Ast0.DParam(id) -> Ast.DParam(ident id)
+ | Ast0.DPComma(comma) -> Ast.DPComma(mcode comma)
+ | Ast0.DPdots(d) -> Ast.DPdots(mcode d)
+ | Ast0.DPcircles(c) -> Ast.DPcircles(mcode c)
+ | Ast0.OptDParam(dp) -> Ast.OptDParam(define_param dp)
+ | Ast0.UniqueDParam(dp) -> Ast.UniqueDParam(define_param dp))
+
+ and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> Ast.WhenNot (notfn a)
+ | Ast0.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
+ | Ast0.WhenModifier(x) -> Ast.WhenModifier(x)
+ | x ->
+ let rewrap_rule_elem ast0 ast =
+ rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
+ match x with
+ Ast0.WhenNotTrue(e) ->
+ Ast.WhenNotTrue(rewrap_rule_elem e (Ast.Exp(expression e)))
+ | Ast0.WhenNotFalse(e) ->
+ Ast.WhenNotFalse(rewrap_rule_elem e (Ast.Exp(expression e)))
+ | _ -> failwith "not possible"
+
+ and process_list seqible isos = function
+ [] -> []
+ | x::rest ->
+ let first = statement seqible x in
+ let first =
+ if !Flag.track_iso_usage
+ then Ast.set_isos first (isos@(Ast.get_isos first))
+ else first in
+ (match Ast0.unwrap x with
+ Ast0.Dots(_,_) | Ast0.Nest(_) ->
+ first::(process_list (Ast.SequencibleAfterDots []) no_isos rest)
+ | _ ->
+ first::(process_list Ast.Sequencible no_isos rest))
+
+ and statement_dots seqible d =
+ let isos = do_isos (Ast0.get_iso d) in
+ rewrap d no_isos
+ (match Ast0.unwrap d with
+ Ast0.DOTS(x) -> Ast.DOTS(process_list seqible isos x)
+ | Ast0.CIRCLES(x) -> Ast.CIRCLES(process_list seqible isos x)
+ | Ast0.STARS(x) -> Ast.STARS(process_list seqible isos x))
+
+ and separate_decls seqible d =
+ let rec collect_decls = function
+ [] -> ([],[])
+ | (x::xs) as l ->
+ (match Ast0.unwrap x with
+ Ast0.Decl(_) ->
+ let (decls,other) = collect_decls xs in
+ (x :: decls,other)
+ | Ast0.Dots(_,_) | Ast0.Nest(_,_,_,_,_) ->
+ let (decls,other) = collect_decls xs in
+ (match decls with
+ [] -> ([],x::other)
+ | _ -> (x :: decls,other))
+ | Ast0.Disj(starter,stmt_dots_list,mids,ender) ->
+ let disjs = List.map collect_dot_decls stmt_dots_list in
+ let all_decls = List.for_all (function (_,s) -> s=[]) disjs in
+ if all_decls
+ then
+ let (decls,other) = collect_decls xs in
+ (x :: decls,other)
+ else ([],l)
+ | _ -> ([],l))
+
+ and collect_dot_decls d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> collect_decls x
+ | Ast0.CIRCLES(x) -> collect_decls x
+ | Ast0.STARS(x) -> collect_decls x in
+
+ let process l d fn =
+ let (decls,other) = collect_decls l in
+ (rewrap d no_isos (fn (List.map (statement seqible) decls)),
+ rewrap d no_isos
+ (fn (process_list seqible (do_isos (Ast0.get_iso d)) other))) in
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> process x d (function x -> Ast.DOTS x)
+ | Ast0.CIRCLES(x) -> process x d (function x -> Ast.CIRCLES x)
+ | Ast0.STARS(x) -> process x d (function x -> Ast.STARS x) in
+
+ statement Ast.Sequencible s
+
+and fninfo = function
+ Ast0.FStorage(stg) -> Ast.FStorage(mcode stg)
+ | Ast0.FType(ty) -> Ast.FType(typeC ty)
+ | Ast0.FInline(inline) -> Ast.FInline(mcode inline)
+ | Ast0.FAttr(attr) -> Ast.FAttr(mcode attr)
+
+and option_to_list = function
+ Some x -> [x]
+ | None -> []
+
+and case_line c =
+ rewrap c no_isos
+ (match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ let def = mcode def in
+ let colon = mcode colon in
+ let code = dots statement code in
+ Ast.CaseLine(rewrap c no_isos (Ast.Default(def,colon)),code)
+ | Ast0.Case(case,exp,colon,code) ->
+ let case = mcode case in
+ let exp = expression exp in
+ let colon = mcode colon in
+ let code = dots statement code in
+ Ast.CaseLine(rewrap c no_isos (Ast.Case(case,exp,colon)),code)
+ | Ast0.OptCase(case) -> Ast.OptCase(case_line case))
+
+and statement_dots l = dots statement l
+
+(* --------------------------------------------------------------------- *)
+
+(* what is possible is only what is at the top level in an iso *)
+and anything = function
+ Ast0.DotsExprTag(d) -> Ast.ExprDotsTag(expression_dots d)
+ | Ast0.DotsParamTag(d) -> Ast.ParamDotsTag(parameter_list d)
+ | Ast0.DotsInitTag(d) -> failwith "not possible"
+ | Ast0.DotsStmtTag(d) -> Ast.StmtDotsTag(statement_dots d)
+ | Ast0.DotsDeclTag(d) -> Ast.DeclDotsTag(declaration_dots d)
+ | Ast0.DotsCaseTag(d) -> failwith "not possible"
+ | Ast0.IdentTag(d) -> Ast.IdentTag(ident d)
+ | Ast0.ExprTag(d) -> Ast.ExpressionTag(expression d)
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "only in isos, not converted to ast"
+ | Ast0.TypeCTag(d) -> Ast.FullTypeTag(typeC d)
+ | Ast0.ParamTag(d) -> Ast.ParamTag(parameterTypeDef d)
+ | Ast0.InitTag(d) -> Ast.InitTag(initialiser d)
+ | Ast0.DeclTag(d) -> Ast.DeclarationTag(declaration d)
+ | Ast0.StmtTag(d) -> Ast.StatementTag(statement d)
+ | Ast0.CaseLineTag(d) -> Ast.CaseLineTag(case_line d)
+ | Ast0.TopTag(d) -> Ast.Code(top_level d)
+ | Ast0.IsoWhenTag(_) -> failwith "not possible"
+ | Ast0.IsoWhenTTag(_) -> failwith "not possible"
+ | Ast0.IsoWhenFTag(_) -> failwith "not possible"
+ | Ast0.MetaPosTag _ -> failwith "not possible"
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+(* top level isos are probably lost to tracking *)
+
+and top_level t =
+ rewrap t no_isos
+ (match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ Ast.FILEINFO(mcode old_file,mcode new_file)
+ | Ast0.DECL(stmt) -> Ast.DECL(statement stmt)
+ | Ast0.CODE(rule_elem_dots) ->
+ Ast.CODE(statement_dots rule_elem_dots)
+ | Ast0.ERRORWORDS(exps) -> Ast.ERRORWORDS(List.map expression exps)
+ | Ast0.OTHER(_) -> failwith "eliminated by top_level")
+
+(* --------------------------------------------------------------------- *)
+(* Entry point for minus code *)
+
+(* Inline_mcodes is very important - sends + code attached to the - code
+down to the mcodes. The functions above can only be used when there is no
+attached + code, eg in + code itself. *)
+let ast0toast_toplevel x =
+ inline_mcodes.V0.combiner_top_level x;
+ top_level x
+
+let ast0toast name deps dropped exists x is_exp =
+ List.iter inline_mcodes.V0.combiner_top_level x;
+ Ast.CocciRule (name,(deps,dropped,exists),List.map top_level x,is_exp)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+type info = { line : int; column : int;
+ strbef : string list; straft : string list }
+type line = int
+type meta_name = string * string
+(* need to be careful about rewrapping, to avoid duplicating pos info
+currently, the pos info is always None until asttoctl2. *)
+type 'a wrap =
+ {node : 'a;
+ node_line : line;
+ free_vars : meta_name list; (*free vars*)
+ minus_free_vars : meta_name list; (*minus free vars*)
+ fresh_vars : meta_name list; (*fresh vars*)
+ inherited : meta_name list; (*inherited vars*)
+ saved_witness : meta_name list; (*witness vars*)
+ bef_aft : dots_bef_aft;
+ (* the following is for or expressions *)
+ pos_info : meta_name mcode option; (* pos info, try not to duplicate *)
+ true_if_test_exp : bool;(* true if "test_exp from iso", only for exprs *)
+ (* isos relevant to the term; ultimately only used for rule_elems *)
+ iso_info : (string*anything) list }
+
+and 'a befaft =
+ BEFORE of 'a list list
+ | AFTER of 'a list list
+ | BEFOREAFTER of 'a list list * 'a list list
+ | NOTHING
+
+and 'a mcode = 'a * info * mcodekind * meta_pos (* pos variable *)
+ (* pos is an offset indicating where in the C code the mcodekind has an
+ effect *)
+ and mcodekind =
+ MINUS of pos * anything list list
+ | CONTEXT of pos * anything befaft
+ | PLUS
+ and fixpos =
+ Real of int (* charpos *) | Virt of int * int (* charpos + offset *)
+ and pos = NoPos | DontCarePos | FixPos of (fixpos * fixpos)
+
+and dots_bef_aft =
+ NoDots
+ | AddingBetweenDots of statement * int (*index of let var*)
+ | DroppingBetweenDots of statement * int (*index of let var*)
+
+and inherited = Type_cocci.inherited
+and keep_binding = Type_cocci.keep_binding
+and multi = bool (*true if a nest is one or more, false if it is zero or more*)
+
+and end_info =
+ meta_name list (*free vars*) * meta_name list (*inherited vars*) *
+ meta_name list (*witness vars*) * mcodekind
+
+(* --------------------------------------------------------------------- *)
+(* Metavariables *)
+
+and arity = UNIQUE | OPT | MULTI | NONE
+
+and metavar =
+ MetaIdDecl of arity * meta_name (* name *)
+ | MetaFreshIdDecl of arity * meta_name (* name *)
+ | MetaTypeDecl of arity * meta_name (* name *)
+ | MetaListlenDecl of meta_name (* name *)
+ | MetaParamDecl of arity * meta_name (* name *)
+ | MetaParamListDecl of arity * meta_name (*name*) * meta_name option (*len*)
+ | MetaConstDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaErrDecl of arity * meta_name (* name *)
+ | MetaExpDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaIdExpDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaLocalIdExpDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaExpListDecl of arity * meta_name (*name*) * meta_name option (*len*)
+ | MetaStmDecl of arity * meta_name (* name *)
+ | MetaStmListDecl of arity * meta_name (* name *)
+ | MetaFuncDecl of arity * meta_name (* name *)
+ | MetaLocalFuncDecl of arity * meta_name (* name *)
+ | MetaPosDecl of arity * meta_name (* name *)
+ | MetaDeclarerDecl of arity * meta_name (* name *)
+ | MetaIteratorDecl of arity * meta_name (* name *)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+and 'a base_dots =
+ DOTS of 'a list
+ | CIRCLES of 'a list
+ | STARS of 'a list
+
+and 'a dots = 'a base_dots wrap
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+and base_ident =
+ Id of string mcode
+
+ | MetaId of meta_name mcode * ident list * keep_binding * inherited
+ | MetaFunc of meta_name mcode * ident list * keep_binding * inherited
+ | MetaLocalFunc of meta_name mcode * ident list * keep_binding * inherited
+
+ | OptIdent of ident
+ | UniqueIdent of ident
+
+and ident = base_ident wrap
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+and base_expression =
+ Ident of ident
+ | Constant of constant mcode
+ | FunCall of expression * string mcode (* ( *) *
+ expression dots * string mcode (* ) *)
+ | Assignment of expression * assignOp mcode * expression *
+ bool (* true if it can match an initialization *)
+ | CondExpr of expression * string mcode (* ? *) * expression option *
+ string mcode (* : *) * expression
+ | Postfix of expression * fixOp mcode
+ | Infix of expression * fixOp mcode
+ | Unary of expression * unaryOp mcode
+ | Binary of expression * binaryOp mcode * expression
+ | Nested of expression * binaryOp mcode * expression
+ | ArrayAccess of expression * string mcode (* [ *) * expression *
+ string mcode (* ] *)
+ | RecordAccess of expression * string mcode (* . *) * ident
+ | RecordPtAccess of expression * string mcode (* -> *) * ident
+ | Cast of string mcode (* ( *) * fullType * string mcode (* ) *) *
+ expression
+ | SizeOfExpr of string mcode (* sizeof *) * expression
+ | SizeOfType of string mcode (* sizeof *) * string mcode (* ( *) *
+ fullType * string mcode (* ) *)
+ | TypeExp of fullType (*type name used as an expression, only in
+ arg or #define*)
+
+ | Paren of string mcode (* ( *) * expression *
+ string mcode (* ) *)
+
+ | MetaErr of meta_name mcode * expression list * keep_binding *
+ inherited
+ | MetaExpr of meta_name mcode * expression list * keep_binding *
+ Type_cocci.typeC list option * form * inherited
+ | MetaExprList of meta_name mcode * listlen option * keep_binding *
+ inherited (* only in arg lists *)
+
+ | EComma of string mcode (* only in arg lists *)
+
+ | DisjExpr of expression list
+ | NestExpr of expression dots * expression option * multi
+
+ (* can appear in arg lists, and also inside Nest, as in:
+ if(< ... X ... Y ...>)
+ In the following, the expression option is the WHEN *)
+ | Edots of string mcode (* ... *) * expression option
+ | Ecircles of string mcode (* ooo *) * expression option
+ | Estars of string mcode (* *** *) * expression option
+
+ | OptExp of expression
+ | UniqueExp of expression
+
+(* ANY = int E; ID = idexpression int X; CONST = constant int X; *)
+and form = ANY | ID | LocalID | CONST (* form for MetaExp *)
+
+and expression = base_expression wrap
+
+and listlen = meta_name mcode * keep_binding * inherited
+
+and unaryOp = GetRef | DeRef | UnPlus | UnMinus | Tilde | Not
+and assignOp = SimpleAssign | OpAssign of arithOp
+and fixOp = Dec | Inc
+
+and binaryOp = Arith of arithOp | Logical of logicalOp
+and arithOp =
+ Plus | Minus | Mul | Div | Mod | DecLeft | DecRight | And | Or | Xor
+and logicalOp = Inf | Sup | InfEq | SupEq | Eq | NotEq | AndLog | OrLog
+
+and constant =
+ String of string
+ | Char of string
+ | Int of string
+ | Float of string
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and base_fullType =
+ Type of const_vol mcode option * typeC
+ | DisjType of fullType list (* only after iso *)
+ | OptType of fullType
+ | UniqueType of fullType
+
+and base_typeC =
+ BaseType of baseType mcode * sign mcode option
+ | ImplicitInt of sign mcode
+ | Pointer of fullType * string mcode (* * *)
+ | FunctionPointer of fullType *
+ string mcode(* ( *)*string mcode(* * *)*string mcode(* ) *)*
+ string mcode (* ( *)*parameter_list*string mcode(* ) *)
+
+ (* used for the automatic managment of prototypes *)
+ | FunctionType of bool (* true if all minus for dropping return type *) *
+ fullType option *
+ string mcode (* ( *) * parameter_list *
+ string mcode (* ) *)
+
+ | Array of fullType * string mcode (* [ *) *
+ expression option * string mcode (* ] *)
+ | StructUnionName of structUnion mcode * ident option (* name *)
+ | StructUnionDef of fullType (* either StructUnionName or metavar *) *
+ string mcode (* { *) * declaration dots * string mcode (* } *)
+ | TypeName of string mcode
+
+ | MetaType of meta_name mcode * keep_binding * inherited
+
+and fullType = base_fullType wrap
+and typeC = base_typeC wrap
+
+and baseType = VoidType | CharType | ShortType | IntType | DoubleType
+| FloatType | LongType
+
+and structUnion = Struct | Union
+
+and sign = Signed | Unsigned
+
+and const_vol = Const | Volatile
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and base_declaration =
+ Init of storage mcode option * fullType * ident * string mcode (*=*) *
+ initialiser * string mcode (*;*)
+ | UnInit of storage mcode option * fullType * ident * string mcode (* ; *)
+ | TyDecl of fullType * string mcode (* ; *)
+ | MacroDecl of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *) * string mcode (* ; *)
+ | Typedef of string mcode (*typedef*) * fullType *
+ typeC (* either TypeName or metavar *) * string mcode (*;*)
+ | DisjDecl of declaration list
+ (* Ddots is for a structure declaration *)
+ | Ddots of string mcode (* ... *) * declaration option (* whencode *)
+
+ | MetaDecl of meta_name mcode * keep_binding * inherited
+
+ | OptDecl of declaration
+ | UniqueDecl of declaration
+
+and declaration = base_declaration wrap
+
+(* --------------------------------------------------------------------- *)
+(* Initializers *)
+
+and base_initialiser =
+ InitExpr of expression
+ | InitList of string mcode (*{*) * initialiser list * string mcode (*}*) *
+ initialiser list (* whencode: elements that shouldn't appear in init *)
+ | InitGccDotName of
+ string mcode (*.*) * ident (* name *) * string mcode (*=*) *
+ initialiser (* gccext: *)
+ | InitGccName of ident (* name *) * string mcode (*:*) *
+ initialiser
+ | InitGccIndex of
+ string mcode (*[*) * expression * string mcode (*]*) *
+ string mcode (*=*) * initialiser
+ | InitGccRange of
+ string mcode (*[*) * expression * string mcode (*...*) *
+ expression * string mcode (*]*) * string mcode (*=*) * initialiser
+ | IComma of string mcode (* , *)
+
+ | OptIni of initialiser
+ | UniqueIni of initialiser
+
+and initialiser = base_initialiser wrap
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and base_parameterTypeDef =
+ VoidParam of fullType
+ | Param of fullType * ident option
+
+ | MetaParam of meta_name mcode * keep_binding * inherited
+ | MetaParamList of meta_name mcode * listlen option * keep_binding *
+ inherited
+
+ | PComma of string mcode
+
+ | Pdots of string mcode (* ... *)
+ | Pcircles of string mcode (* ooo *)
+
+ | OptParam of parameterTypeDef
+ | UniqueParam of parameterTypeDef
+
+and parameterTypeDef = base_parameterTypeDef wrap
+
+and parameter_list = parameterTypeDef dots
+
+(* --------------------------------------------------------------------- *)
+(* #define Parameters *)
+
+and base_define_param =
+ DParam of ident
+ | DPComma of string mcode
+ | DPdots of string mcode (* ... *)
+ | DPcircles of string mcode (* ooo *)
+ | OptDParam of define_param
+ | UniqueDParam of define_param
+
+and define_param = base_define_param wrap
+
+and base_define_parameters =
+ NoParams (* not parameter list, not an empty one *)
+ | DParams of string mcode(*( *) * define_param dots * string mcode(* )*)
+
+and define_parameters = base_define_parameters wrap
+
+(* --------------------------------------------------------------------- *)
+(* positions *)
+
+(* PER = keep bindings separate, ALL = collect them *)
+and meta_collect = PER | ALL
+
+and meta_pos =
+ MetaPos of meta_name mcode * meta_name list *
+ meta_collect * keep_binding * inherited
+ | NoMetaPos
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+
+and storage = Static | Auto | Register | Extern
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and base_rule_elem =
+ FunHeader of mcodekind (* before the function header *) *
+ bool (* true if all minus, for dropping static, etc *) *
+ fninfo list * ident (* name *) *
+ string mcode (* ( *) * parameter_list *
+ string mcode (* ) *)
+ | Decl of mcodekind (* before the decl *) *
+ bool (* true if all minus *) * declaration
+
+ | SeqStart of string mcode (* { *)
+ | SeqEnd of string mcode (* } *)
+
+ | ExprStatement of expression * string mcode (*;*)
+ | IfHeader of string mcode (* if *) * string mcode (* ( *) *
+ expression * string mcode (* ) *)
+ | Else of string mcode (* else *)
+ | WhileHeader of string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *)
+ | DoHeader of string mcode (* do *)
+ | WhileTail of string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ string mcode (* ; *)
+ | ForHeader of string mcode (* for *) * string mcode (* ( *) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (* ) *)
+ | IteratorHeader of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *)
+ | SwitchHeader of string mcode (* switch *) * string mcode (* ( *) *
+ expression * string mcode (* ) *)
+ | Break of string mcode (* break *) * string mcode (* ; *)
+ | Continue of string mcode (* continue *) * string mcode (* ; *)
+ | Label of ident * string mcode (* : *)
+ | Goto of string mcode (* goto *) * ident * string mcode (* ; *)
+ | Return of string mcode (* return *) * string mcode (* ; *)
+ | ReturnExpr of string mcode (* return *) * expression *
+ string mcode (* ; *)
+
+ | MetaRuleElem of meta_name mcode * keep_binding * inherited
+ | MetaStmt of meta_name mcode * keep_binding * metaStmtInfo *
+ inherited
+ | MetaStmtList of meta_name mcode * keep_binding * inherited
+
+ | Exp of expression (* matches a subterm *)
+ | TopExp of expression (* for macros body, exp at top level,
+ not subexp *)
+ | Ty of fullType (* only at SP top level, matches a subterm *)
+ | Include of string mcode (*#include*) * inc_file mcode (*file *)
+ | DefineHeader of string mcode (* #define *) * ident (* name *) *
+ define_parameters (*params*)
+ | Case of string mcode (* case *) * expression * string mcode (*:*)
+ | Default of string mcode (* default *) * string mcode (*:*)
+ | DisjRuleElem of rule_elem list
+
+and fninfo =
+ FStorage of storage mcode
+ | FType of fullType
+ | FInline of string mcode
+ | FAttr of string mcode
+
+and metaStmtInfo =
+ NotSequencible | SequencibleAfterDots of dots_whencode list | Sequencible
+
+and rule_elem = base_rule_elem wrap
+
+and base_statement =
+ Seq of rule_elem (* { *) * statement dots *
+ statement dots * rule_elem (* } *)
+ | IfThen of rule_elem (* header *) * statement * end_info (* endif *)
+ | IfThenElse of rule_elem (* header *) * statement *
+ rule_elem (* else *) * statement * end_info (* endif *)
+ | While of rule_elem (* header *) * statement * end_info (*endwhile*)
+ | Do of rule_elem (* do *) * statement * rule_elem (* tail *)
+ | For of rule_elem (* header *) * statement * end_info (*endfor*)
+ | Iterator of rule_elem (* header *) * statement * end_info (*enditer*)
+ | Switch of rule_elem (* header *) * rule_elem (* { *) *
+ case_line list * rule_elem (* } *)
+ | Atomic of rule_elem
+ | Disj of statement dots list
+ | Nest of statement dots *
+ (statement dots,statement) whencode list * multi *
+ dots_whencode list * dots_whencode list
+ | FunDecl of rule_elem (* header *) * rule_elem (* { *) *
+ statement dots * statement dots * rule_elem (* } *)
+ | Define of rule_elem (* header *) * statement dots
+ | Dots of string mcode (* ... *) *
+ (statement dots,statement) whencode list *
+ dots_whencode list * dots_whencode list
+ | Circles of string mcode (* ooo *) *
+ (statement dots,statement) whencode list *
+ dots_whencode list * dots_whencode list
+ | Stars of string mcode (* *** *) *
+ (statement dots,statement) whencode list *
+ dots_whencode list * dots_whencode list
+ | OptStm of statement
+ | UniqueStm of statement
+
+and ('a,'b) whencode =
+ WhenNot of 'a
+ | WhenAlways of 'b
+ | WhenModifier of when_modifier
+
+and when_modifier =
+ (* The following removes the shortest path constraint. It can be used
+ with other when modifiers *)
+ WhenAny
+ (* The following removes the special consideration of error paths. It
+ can be used with other when modifiers *)
+ | WhenStrict
+ | WhenForall
+ | WhenExists
+
+(* only used with asttoctl *)
+and dots_whencode =
+ WParen of rule_elem * meta_name (*pren_var*)
+ | Other of statement
+ | Other_dots of statement dots
+
+and statement = base_statement wrap
+
+and base_case_line =
+ CaseLine of rule_elem (* case/default header *) * statement dots
+ | OptCase of case_line
+
+and case_line = base_case_line wrap
+
+and inc_file =
+ Local of inc_elem list
+ | NonLocal of inc_elem list
+
+and inc_elem =
+ IncPath of string
+ | IncDots
+
+and base_top_level =
+ DECL of statement
+ | CODE of statement dots
+ | FILEINFO of string mcode (* old file *) * string mcode (* new file *)
+ | ERRORWORDS of expression list
+
+and top_level = base_top_level wrap
+
+and rulename =
+ CocciRulename of string option * dependency *
+ string list * string list * exists * bool
+ | ScriptRulename of string * dependency
+
+and rule =
+ CocciRule of string (* name *) *
+ (dependency * string list (* dropped isos *) * exists) * top_level list
+ * bool list
+ | ScriptRule of string * dependency * (string * meta_name) list * string
+
+and dependency =
+ Dep of string (* rule applies for the current binding *)
+ | AntiDep of string (* rule doesn't apply for the current binding *)
+ | EverDep of string (* rule applies for some binding *)
+ | NeverDep of string (* rule never applies for any binding *)
+ | AndDep of dependency * dependency
+ | OrDep of dependency * dependency
+ | NoDep
+
+and rule_with_metavars = metavar list * rule
+
+and anything =
+ FullTypeTag of fullType
+ | BaseTypeTag of baseType
+ | StructUnionTag of structUnion
+ | SignTag of sign
+ | IdentTag of ident
+ | ExpressionTag of expression
+ | ConstantTag of constant
+ | UnaryOpTag of unaryOp
+ | AssignOpTag of assignOp
+ | FixOpTag of fixOp
+ | BinaryOpTag of binaryOp
+ | ArithOpTag of arithOp
+ | LogicalOpTag of logicalOp
+ | DeclarationTag of declaration
+ | InitTag of initialiser
+ | StorageTag of storage
+ | IncFileTag of inc_file
+ | Rule_elemTag of rule_elem
+ | StatementTag of statement
+ | CaseLineTag of case_line
+ | ConstVolTag of const_vol
+ | Token of string * info option
+ | Code of top_level
+ | ExprDotsTag of expression dots
+ | ParamDotsTag of parameterTypeDef dots
+ | StmtDotsTag of statement dots
+ | DeclDotsTag of declaration dots
+ | TypeCTag of typeC
+ | ParamTag of parameterTypeDef
+ | SgrepStartTag of string
+ | SgrepEndTag of string
+
+(* --------------------------------------------------------------------- *)
+
+and exists = Exists | Forall | ReverseForall | Undetermined
+
+(* --------------------------------------------------------------------- *)
+
+let mkToken x = Token (x,None)
+
+(* --------------------------------------------------------------------- *)
+
+let rewrap model x = {model with node = x}
+let rewrap_mcode (_,a,b,c) x = (x,a,b,c)
+let unwrap x = x.node
+let unwrap_mcode (x,_,_,_) = x
+let get_mcodekind (_,_,x,_) = x
+let get_line x = x.node_line
+let get_mcode_line (_,l,_,_) = l.line
+let get_fvs x = x.free_vars
+let set_fvs fvs x = {x with free_vars = fvs}
+let get_mfvs x = x.minus_free_vars
+let set_mfvs mfvs x = {x with minus_free_vars = mfvs}
+let get_fresh x = x.fresh_vars
+let get_inherited x = x.inherited
+let get_saved x = x.saved_witness
+let get_dots_bef_aft x = x.bef_aft
+let set_dots_bef_aft d x = {x with bef_aft = d}
+let get_pos x = x.pos_info
+let set_pos x pos = {x with pos_info = pos}
+let get_test_exp x = x.true_if_test_exp
+let set_test_exp x = {x with true_if_test_exp = true}
+let get_isos x = x.iso_info
+let set_isos x isos = {x with iso_info = isos}
+let get_pos_var (_,_,_,p) = p
+let set_pos_var vr (a,b,c,_) = (a,b,c,vr)
+let drop_pos (a,b,c,_) = (a,b,c,NoMetaPos)
+
+let get_wcfvs (whencode : ('a wrap, 'b wrap) whencode list) =
+ Common.union_all
+ (List.map
+ (function
+ WhenNot(a) -> get_fvs a
+ | WhenAlways(a) -> get_fvs a
+ | WhenModifier(_) -> [])
+ whencode)
+
+(* --------------------------------------------------------------------- *)
+
+let get_meta_name = function
+ MetaIdDecl(ar,nm) -> nm
+ | MetaFreshIdDecl(ar,nm) -> nm
+ | MetaTypeDecl(ar,nm) -> nm
+ | MetaListlenDecl(nm) -> nm
+ | MetaParamDecl(ar,nm) -> nm
+ | MetaParamListDecl(ar,nm,nm1) -> nm
+ | MetaConstDecl(ar,nm,ty) -> nm
+ | MetaErrDecl(ar,nm) -> nm
+ | MetaExpDecl(ar,nm,ty) -> nm
+ | MetaIdExpDecl(ar,nm,ty) -> nm
+ | MetaLocalIdExpDecl(ar,nm,ty) -> nm
+ | MetaExpListDecl(ar,nm,nm1) -> nm
+ | MetaStmDecl(ar,nm) -> nm
+ | MetaStmListDecl(ar,nm) -> nm
+ | MetaFuncDecl(ar,nm) -> nm
+ | MetaLocalFuncDecl(ar,nm) -> nm
+ | MetaPosDecl(ar,nm) -> nm
+ | MetaDeclarerDecl(ar,nm) -> nm
+ | MetaIteratorDecl(ar,nm) -> nm
+
+(* --------------------------------------------------------------------- *)
+
+let no_info = { line = 0; column = 0; strbef = []; straft = [] }
+
+let make_term x =
+ {node = x;
+ node_line = 0;
+ free_vars = [];
+ minus_free_vars = [];
+ fresh_vars = [];
+ inherited = [];
+ saved_witness = [];
+ bef_aft = NoDots;
+ pos_info = None;
+ true_if_test_exp = false;
+ iso_info = [] }
+
+let make_meta_rule_elem s d (fvs,fresh,inh) =
+ {(make_term
+ (MetaRuleElem((("",s),no_info,d,NoMetaPos),Type_cocci.Unitary,false)))
+ with free_vars = fvs; fresh_vars = fresh; inherited = inh}
+
+let make_meta_decl s d (fvs,fresh,inh) =
+ {(make_term
+ (MetaDecl((("",s),no_info,d,NoMetaPos),Type_cocci.Unitary,false))) with
+ free_vars = fvs; fresh_vars = fresh; inherited = inh}
+
+let make_mcode x = (x,no_info,CONTEXT(NoPos,NOTHING),NoMetaPos)
+
+(* --------------------------------------------------------------------- *)
+
+let equal_pos x y = x = y
+
+(* --------------------------------------------------------------------- *)
+
+let undots x =
+ match unwrap x with
+ DOTS e -> e
+ | CIRCLES e -> e
+ | STARS e -> e
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+type info = { line : int; column : int;
+ strbef : string list; straft : string list }
+type line = int
+type meta_name = string * string
+(* need to be careful about rewrapping, to avoid duplicating pos info
+currently, the pos info is always None until asttoctl2. *)
+type 'a wrap =
+ {node : 'a;
+ node_line : line;
+ free_vars : meta_name list; (*free vars*)
+ minus_free_vars : meta_name list; (*minus free vars*)
+ fresh_vars : meta_name list; (*fresh vars*)
+ inherited : meta_name list; (*inherited vars*)
+ saved_witness : meta_name list; (*witness vars*)
+ bef_aft : dots_bef_aft;
+ (* the following is for or expressions *)
+ pos_info : meta_name mcode option; (* pos info, try not to duplicate *)
+ true_if_test_exp : bool;(* true if "test_exp from iso", only for exprs *)
+ (* isos relevant to the term; ultimately only used for rule_elems *)
+ iso_info : (string*anything) list }
+
+and 'a befaft =
+ BEFORE of 'a list list
+ | AFTER of 'a list list
+ | BEFOREAFTER of 'a list list * 'a list list
+ | NOTHING
+
+and 'a mcode = 'a * info * mcodekind * meta_pos (* pos variable *)
+ (* pos is an offset indicating where in the C code the mcodekind has an
+ effect *)
+ and mcodekind =
+ MINUS of pos * anything list list
+ | CONTEXT of pos * anything befaft
+ | PLUS
+ and fixpos =
+ Real of int (* charpos *) | Virt of int * int (* charpos + offset *)
+ and pos = NoPos | DontCarePos | FixPos of (fixpos * fixpos)
+
+and dots_bef_aft =
+ NoDots
+ | AddingBetweenDots of statement * int (*index of let var*)
+ | DroppingBetweenDots of statement * int (*index of let var*)
+
+and inherited = Type_cocci.inherited
+and keep_binding = Type_cocci.keep_binding
+and multi = bool (*true if a nest is one or more, false if it is zero or more*)
+
+and end_info =
+ meta_name list (*free vars*) * meta_name list (*inherited vars*) *
+ meta_name list (*witness vars*) * mcodekind
+
+(* --------------------------------------------------------------------- *)
+(* Metavariables *)
+
+and arity = UNIQUE | OPT | MULTI | NONE
+
+and metavar =
+ MetaIdDecl of arity * meta_name (* name *)
+ | MetaFreshIdDecl of arity * meta_name (* name *)
+ | MetaTypeDecl of arity * meta_name (* name *)
+ | MetaListlenDecl of meta_name (* name *)
+ | MetaParamDecl of arity * meta_name (* name *)
+ | MetaParamListDecl of arity * meta_name (*name*) * meta_name option (*len*)
+ | MetaConstDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaErrDecl of arity * meta_name (* name *)
+ | MetaExpDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaIdExpDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaLocalIdExpDecl of
+ arity * meta_name (* name *) * Type_cocci.typeC list option
+ | MetaExpListDecl of arity * meta_name (*name*) * meta_name option (*len*)
+ | MetaStmDecl of arity * meta_name (* name *)
+ | MetaStmListDecl of arity * meta_name (* name *)
+ | MetaFuncDecl of arity * meta_name (* name *)
+ | MetaLocalFuncDecl of arity * meta_name (* name *)
+ | MetaPosDecl of arity * meta_name (* name *)
+ | MetaDeclarerDecl of arity * meta_name (* name *)
+ | MetaIteratorDecl of arity * meta_name (* name *)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+and 'a base_dots =
+ DOTS of 'a list
+ | CIRCLES of 'a list
+ | STARS of 'a list
+
+and 'a dots = 'a base_dots wrap
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+and base_ident =
+ Id of string mcode
+
+ | MetaId of meta_name mcode * ident list * keep_binding * inherited
+ | MetaFunc of meta_name mcode * ident list * keep_binding * inherited
+ | MetaLocalFunc of meta_name mcode * ident list * keep_binding * inherited
+
+ | OptIdent of ident
+ | UniqueIdent of ident
+
+and ident = base_ident wrap
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+and base_expression =
+ Ident of ident
+ | Constant of constant mcode
+ | FunCall of expression * string mcode (* ( *) *
+ expression dots * string mcode (* ) *)
+ | Assignment of expression * assignOp mcode * expression *
+ bool (* true if it can match an initialization *)
+ | CondExpr of expression * string mcode (* ? *) * expression option *
+ string mcode (* : *) * expression
+ | Postfix of expression * fixOp mcode
+ | Infix of expression * fixOp mcode
+ | Unary of expression * unaryOp mcode
+ | Binary of expression * binaryOp mcode * expression
+ | Nested of expression * binaryOp mcode * expression
+ | ArrayAccess of expression * string mcode (* [ *) * expression *
+ string mcode (* ] *)
+ | RecordAccess of expression * string mcode (* . *) * ident
+ | RecordPtAccess of expression * string mcode (* -> *) * ident
+ | Cast of string mcode (* ( *) * fullType * string mcode (* ) *) *
+ expression
+ | SizeOfExpr of string mcode (* sizeof *) * expression
+ | SizeOfType of string mcode (* sizeof *) * string mcode (* ( *) *
+ fullType * string mcode (* ) *)
+ | TypeExp of fullType (*type name used as an expression, only in
+ arg or #define*)
+
+ | Paren of string mcode (* ( *) * expression *
+ string mcode (* ) *)
+
+ | MetaErr of meta_name mcode * expression list * keep_binding *
+ inherited
+ | MetaExpr of meta_name mcode * expression list * keep_binding *
+ Type_cocci.typeC list option * form * inherited
+ | MetaExprList of meta_name mcode * listlen option * keep_binding *
+ inherited (* only in arg lists *)
+
+ | EComma of string mcode (* only in arg lists *)
+
+ | DisjExpr of expression list
+ | NestExpr of expression dots * expression option * multi
+
+ (* can appear in arg lists, and also inside Nest, as in:
+ if(< ... X ... Y ...>)
+ In the following, the expression option is the WHEN *)
+ | Edots of string mcode (* ... *) * expression option
+ | Ecircles of string mcode (* ooo *) * expression option
+ | Estars of string mcode (* *** *) * expression option
+
+ | OptExp of expression
+ | UniqueExp of expression
+
+(* ANY = int E; ID = idexpression int X; CONST = constant int X; *)
+and form = ANY | ID | LocalID | CONST (* form for MetaExp *)
+
+and expression = base_expression wrap
+
+and listlen = meta_name mcode * keep_binding * inherited
+
+and unaryOp = GetRef | DeRef | UnPlus | UnMinus | Tilde | Not
+and assignOp = SimpleAssign | OpAssign of arithOp
+and fixOp = Dec | Inc
+
+and binaryOp = Arith of arithOp | Logical of logicalOp
+and arithOp =
+ Plus | Minus | Mul | Div | Mod | DecLeft | DecRight | And | Or | Xor
+and logicalOp = Inf | Sup | InfEq | SupEq | Eq | NotEq | AndLog | OrLog
+
+and constant =
+ String of string
+ | Char of string
+ | Int of string
+ | Float of string
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and base_fullType =
+ Type of const_vol mcode option * typeC
+ | DisjType of fullType list (* only after iso *)
+ | OptType of fullType
+ | UniqueType of fullType
+
+and base_typeC =
+ BaseType of baseType mcode * sign mcode option
+ | ImplicitInt of sign mcode
+ | Pointer of fullType * string mcode (* * *)
+ | FunctionPointer of fullType *
+ string mcode(* ( *)*string mcode(* * *)*string mcode(* ) *)*
+ string mcode (* ( *)*parameter_list*string mcode(* ) *)
+
+ (* used for the automatic managment of prototypes *)
+ | FunctionType of bool (* true if all minus for dropping return type *) *
+ fullType option *
+ string mcode (* ( *) * parameter_list *
+ string mcode (* ) *)
+
+ | Array of fullType * string mcode (* [ *) *
+ expression option * string mcode (* ] *)
+ | StructUnionName of structUnion mcode * ident option (* name *)
+ | StructUnionDef of fullType (* either StructUnionName or metavar *) *
+ string mcode (* { *) * declaration dots * string mcode (* } *)
+ | TypeName of string mcode
+
+ | MetaType of meta_name mcode * keep_binding * inherited
+
+and fullType = base_fullType wrap
+and typeC = base_typeC wrap
+
+and baseType = VoidType | CharType | ShortType | IntType | DoubleType
+| FloatType | LongType
+
+and structUnion = Struct | Union
+
+and sign = Signed | Unsigned
+
+and const_vol = Const | Volatile
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and base_declaration =
+ Init of storage mcode option * fullType * ident * string mcode (*=*) *
+ initialiser * string mcode (*;*)
+ | UnInit of storage mcode option * fullType * ident * string mcode (* ; *)
+ | TyDecl of fullType * string mcode (* ; *)
+ | MacroDecl of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *) * string mcode (* ; *)
+ | Typedef of string mcode (*typedef*) * fullType *
+ typeC (* either TypeName or metavar *) * string mcode (*;*)
+ | DisjDecl of declaration list
+ (* Ddots is for a structure declaration *)
+ | Ddots of string mcode (* ... *) * declaration option (* whencode *)
+
+ | MetaDecl of meta_name mcode * keep_binding * inherited
+
+ | OptDecl of declaration
+ | UniqueDecl of declaration
+
+and declaration = base_declaration wrap
+
+(* --------------------------------------------------------------------- *)
+(* Initializers *)
+
+and base_initialiser =
+ InitExpr of expression
+ | InitList of string mcode (*{*) * initialiser list * string mcode (*}*) *
+ initialiser list (* whencode: elements that shouldn't appear in init *)
+ | InitGccDotName of
+ string mcode (*.*) * ident (* name *) * string mcode (*=*) *
+ initialiser (* gccext: *)
+ | InitGccName of ident (* name *) * string mcode (*:*) *
+ initialiser
+ | InitGccIndex of
+ string mcode (*[*) * expression * string mcode (*]*) *
+ string mcode (*=*) * initialiser
+ | InitGccRange of
+ string mcode (*[*) * expression * string mcode (*...*) *
+ expression * string mcode (*]*) * string mcode (*=*) * initialiser
+ | IComma of string mcode (* , *)
+
+ | OptIni of initialiser
+ | UniqueIni of initialiser
+
+and initialiser = base_initialiser wrap
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and base_parameterTypeDef =
+ VoidParam of fullType
+ | Param of fullType * ident option
+
+ | MetaParam of meta_name mcode * keep_binding * inherited
+ | MetaParamList of meta_name mcode * listlen option * keep_binding *
+ inherited
+
+ | PComma of string mcode
+
+ | Pdots of string mcode (* ... *)
+ | Pcircles of string mcode (* ooo *)
+
+ | OptParam of parameterTypeDef
+ | UniqueParam of parameterTypeDef
+
+and parameterTypeDef = base_parameterTypeDef wrap
+
+and parameter_list = parameterTypeDef dots
+
+(* --------------------------------------------------------------------- *)
+(* #define Parameters *)
+
+and base_define_param =
+ DParam of ident
+ | DPComma of string mcode
+ | DPdots of string mcode (* ... *)
+ | DPcircles of string mcode (* ooo *)
+ | OptDParam of define_param
+ | UniqueDParam of define_param
+
+and define_param = base_define_param wrap
+
+and base_define_parameters =
+ NoParams (* not parameter list, not an empty one *)
+ | DParams of string mcode(*( *) * define_param dots * string mcode(* )*)
+
+and define_parameters = base_define_parameters wrap
+
+(* --------------------------------------------------------------------- *)
+(* positions *)
+
+(* PER = keep bindings separate, ALL = collect them *)
+and meta_collect = PER | ALL
+
+and meta_pos =
+ MetaPos of meta_name mcode * meta_name list *
+ meta_collect * keep_binding * inherited
+ | NoMetaPos
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+
+and storage = Static | Auto | Register | Extern
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and base_rule_elem =
+ FunHeader of mcodekind (* before the function header *) *
+ bool (* true if all minus, for dropping static, etc *) *
+ fninfo list * ident (* name *) *
+ string mcode (* ( *) * parameter_list *
+ string mcode (* ) *)
+ | Decl of mcodekind (* before the decl *) *
+ bool (* true if all minus *) * declaration
+
+ | SeqStart of string mcode (* { *)
+ | SeqEnd of string mcode (* } *)
+
+ | ExprStatement of expression * string mcode (*;*)
+ | IfHeader of string mcode (* if *) * string mcode (* ( *) *
+ expression * string mcode (* ) *)
+ | Else of string mcode (* else *)
+ | WhileHeader of string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *)
+ | DoHeader of string mcode (* do *)
+ | WhileTail of string mcode (* while *) * string mcode (* ( *) *
+ expression * string mcode (* ) *) *
+ string mcode (* ; *)
+ | ForHeader of string mcode (* for *) * string mcode (* ( *) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (*;*) *
+ expression option * string mcode (* ) *)
+ | IteratorHeader of ident (* name *) * string mcode (* ( *) *
+ expression dots * string mcode (* ) *)
+ | SwitchHeader of string mcode (* switch *) * string mcode (* ( *) *
+ expression * string mcode (* ) *)
+ | Break of string mcode (* break *) * string mcode (* ; *)
+ | Continue of string mcode (* continue *) * string mcode (* ; *)
+ | Label of ident * string mcode (* : *)
+ | Goto of string mcode (* goto *) * ident * string mcode (* ; *)
+ | Return of string mcode (* return *) * string mcode (* ; *)
+ | ReturnExpr of string mcode (* return *) * expression *
+ string mcode (* ; *)
+
+ | MetaRuleElem of meta_name mcode * keep_binding * inherited
+ | MetaStmt of meta_name mcode * keep_binding * metaStmtInfo *
+ inherited
+ | MetaStmtList of meta_name mcode * keep_binding * inherited
+
+ | Exp of expression (* matches a subterm *)
+ | TopExp of expression (* for macros body, exp at top level,
+ not subexp *)
+ | Ty of fullType (* only at SP top level, matches a subterm *)
+ | Include of string mcode (*#include*) * inc_file mcode (*file *)
+ | DefineHeader of string mcode (* #define *) * ident (* name *) *
+ define_parameters (*params*)
+ | Case of string mcode (* case *) * expression * string mcode (*:*)
+ | Default of string mcode (* default *) * string mcode (*:*)
+ | DisjRuleElem of rule_elem list
+
+and fninfo =
+ FStorage of storage mcode
+ | FType of fullType
+ | FInline of string mcode
+ | FAttr of string mcode
+
+and metaStmtInfo =
+ NotSequencible | SequencibleAfterDots of dots_whencode list | Sequencible
+
+and rule_elem = base_rule_elem wrap
+
+and base_statement =
+ Seq of rule_elem (* { *) * statement dots *
+ statement dots * rule_elem (* } *)
+ | IfThen of rule_elem (* header *) * statement * end_info (* endif *)
+ | IfThenElse of rule_elem (* header *) * statement *
+ rule_elem (* else *) * statement * end_info (* endif *)
+ | While of rule_elem (* header *) * statement * end_info (*endwhile*)
+ | Do of rule_elem (* do *) * statement * rule_elem (* tail *)
+ | For of rule_elem (* header *) * statement * end_info (*endfor*)
+ | Iterator of rule_elem (* header *) * statement * end_info (*enditer*)
+ | Switch of rule_elem (* header *) * rule_elem (* { *) *
+ case_line list * rule_elem (* } *)
+ | Atomic of rule_elem
+ | Disj of statement dots list
+ | Nest of statement dots *
+ (statement dots,statement) whencode list * multi *
+ dots_whencode list * dots_whencode list
+ | FunDecl of rule_elem (* header *) * rule_elem (* { *) *
+ statement dots * statement dots * rule_elem (* } *)
+ | Define of rule_elem (* header *) * statement dots
+ | Dots of string mcode (* ... *) *
+ (statement dots,statement) whencode list *
+ dots_whencode list * dots_whencode list
+ | Circles of string mcode (* ooo *) *
+ (statement dots,statement) whencode list *
+ dots_whencode list * dots_whencode list
+ | Stars of string mcode (* *** *) *
+ (statement dots,statement) whencode list *
+ dots_whencode list * dots_whencode list
+ | OptStm of statement
+ | UniqueStm of statement
+
+and ('a,'b) whencode =
+ WhenNot of 'a
+ | WhenAlways of 'b
+ | WhenModifier of when_modifier
+ | WhenNotTrue of rule_elem (* useful for fvs *)
+ | WhenNotFalse of rule_elem
+
+and when_modifier =
+ (* The following removes the shortest path constraint. It can be used
+ with other when modifiers *)
+ WhenAny
+ (* The following removes the special consideration of error paths. It
+ can be used with other when modifiers *)
+ | WhenStrict
+ | WhenForall
+ | WhenExists
+
+(* only used with asttoctl *)
+and dots_whencode =
+ WParen of rule_elem * meta_name (*pren_var*)
+ | Other of statement
+ | Other_dots of statement dots
+
+and statement = base_statement wrap
+
+and base_case_line =
+ CaseLine of rule_elem (* case/default header *) * statement dots
+ | OptCase of case_line
+
+and case_line = base_case_line wrap
+
+and inc_file =
+ Local of inc_elem list
+ | NonLocal of inc_elem list
+
+and inc_elem =
+ IncPath of string
+ | IncDots
+
+and base_top_level =
+ DECL of statement
+ | CODE of statement dots
+ | FILEINFO of string mcode (* old file *) * string mcode (* new file *)
+ | ERRORWORDS of expression list
+
+and top_level = base_top_level wrap
+
+and rulename =
+ CocciRulename of string option * dependency *
+ string list * string list * exists * bool
+ | ScriptRulename of string * dependency
+
+and rule =
+ CocciRule of string (* name *) *
+ (dependency * string list (* dropped isos *) * exists) * top_level list
+ * bool list
+ | ScriptRule of string * dependency * (string * meta_name) list * string
+
+and dependency =
+ Dep of string (* rule applies for the current binding *)
+ | AntiDep of string (* rule doesn't apply for the current binding *)
+ | EverDep of string (* rule applies for some binding *)
+ | NeverDep of string (* rule never applies for any binding *)
+ | AndDep of dependency * dependency
+ | OrDep of dependency * dependency
+ | NoDep
+
+and rule_with_metavars = metavar list * rule
+
+and anything =
+ FullTypeTag of fullType
+ | BaseTypeTag of baseType
+ | StructUnionTag of structUnion
+ | SignTag of sign
+ | IdentTag of ident
+ | ExpressionTag of expression
+ | ConstantTag of constant
+ | UnaryOpTag of unaryOp
+ | AssignOpTag of assignOp
+ | FixOpTag of fixOp
+ | BinaryOpTag of binaryOp
+ | ArithOpTag of arithOp
+ | LogicalOpTag of logicalOp
+ | DeclarationTag of declaration
+ | InitTag of initialiser
+ | StorageTag of storage
+ | IncFileTag of inc_file
+ | Rule_elemTag of rule_elem
+ | StatementTag of statement
+ | CaseLineTag of case_line
+ | ConstVolTag of const_vol
+ | Token of string * info option
+ | Code of top_level
+ | ExprDotsTag of expression dots
+ | ParamDotsTag of parameterTypeDef dots
+ | StmtDotsTag of statement dots
+ | DeclDotsTag of declaration dots
+ | TypeCTag of typeC
+ | ParamTag of parameterTypeDef
+ | SgrepStartTag of string
+ | SgrepEndTag of string
+
+(* --------------------------------------------------------------------- *)
+
+and exists = Exists | Forall | ReverseForall | Undetermined
+
+(* --------------------------------------------------------------------- *)
+
+let mkToken x = Token (x,None)
+
+(* --------------------------------------------------------------------- *)
+
+let rewrap model x = {model with node = x}
+let rewrap_mcode (_,a,b,c) x = (x,a,b,c)
+let unwrap x = x.node
+let unwrap_mcode (x,_,_,_) = x
+let get_mcodekind (_,_,x,_) = x
+let get_line x = x.node_line
+let get_mcode_line (_,l,_,_) = l.line
+let get_fvs x = x.free_vars
+let set_fvs fvs x = {x with free_vars = fvs}
+let get_mfvs x = x.minus_free_vars
+let set_mfvs mfvs x = {x with minus_free_vars = mfvs}
+let get_fresh x = x.fresh_vars
+let get_inherited x = x.inherited
+let get_saved x = x.saved_witness
+let get_dots_bef_aft x = x.bef_aft
+let set_dots_bef_aft d x = {x with bef_aft = d}
+let get_pos x = x.pos_info
+let set_pos x pos = {x with pos_info = pos}
+let get_test_exp x = x.true_if_test_exp
+let set_test_exp x = {x with true_if_test_exp = true}
+let get_isos x = x.iso_info
+let set_isos x isos = {x with iso_info = isos}
+let get_pos_var (_,_,_,p) = p
+let set_pos_var vr (a,b,c,_) = (a,b,c,vr)
+let drop_pos (a,b,c,_) = (a,b,c,NoMetaPos)
+
+let get_wcfvs (whencode : ('a wrap, 'b wrap) whencode list) =
+ Common.union_all
+ (List.map
+ (function
+ WhenNot(a) -> get_fvs a
+ | WhenAlways(a) -> get_fvs a
+ | WhenModifier(_) -> []
+ | WhenNotTrue(e) -> get_fvs e
+ | WhenNotFalse(e) -> get_fvs e)
+ whencode)
+
+(* --------------------------------------------------------------------- *)
+
+let get_meta_name = function
+ MetaIdDecl(ar,nm) -> nm
+ | MetaFreshIdDecl(ar,nm) -> nm
+ | MetaTypeDecl(ar,nm) -> nm
+ | MetaListlenDecl(nm) -> nm
+ | MetaParamDecl(ar,nm) -> nm
+ | MetaParamListDecl(ar,nm,nm1) -> nm
+ | MetaConstDecl(ar,nm,ty) -> nm
+ | MetaErrDecl(ar,nm) -> nm
+ | MetaExpDecl(ar,nm,ty) -> nm
+ | MetaIdExpDecl(ar,nm,ty) -> nm
+ | MetaLocalIdExpDecl(ar,nm,ty) -> nm
+ | MetaExpListDecl(ar,nm,nm1) -> nm
+ | MetaStmDecl(ar,nm) -> nm
+ | MetaStmListDecl(ar,nm) -> nm
+ | MetaFuncDecl(ar,nm) -> nm
+ | MetaLocalFuncDecl(ar,nm) -> nm
+ | MetaPosDecl(ar,nm) -> nm
+ | MetaDeclarerDecl(ar,nm) -> nm
+ | MetaIteratorDecl(ar,nm) -> nm
+
+(* --------------------------------------------------------------------- *)
+
+let no_info = { line = 0; column = 0; strbef = []; straft = [] }
+
+let make_term x =
+ {node = x;
+ node_line = 0;
+ free_vars = [];
+ minus_free_vars = [];
+ fresh_vars = [];
+ inherited = [];
+ saved_witness = [];
+ bef_aft = NoDots;
+ pos_info = None;
+ true_if_test_exp = false;
+ iso_info = [] }
+
+let make_meta_rule_elem s d (fvs,fresh,inh) =
+ {(make_term
+ (MetaRuleElem((("",s),no_info,d,NoMetaPos),Type_cocci.Unitary,false)))
+ with free_vars = fvs; fresh_vars = fresh; inherited = inh}
+
+let make_meta_decl s d (fvs,fresh,inh) =
+ {(make_term
+ (MetaDecl((("",s),no_info,d,NoMetaPos),Type_cocci.Unitary,false))) with
+ free_vars = fvs; fresh_vars = fresh; inherited = inh}
+
+let make_mcode x = (x,no_info,CONTEXT(NoPos,NOTHING),NoMetaPos)
+
+(* --------------------------------------------------------------------- *)
+
+let equal_pos x y = x = y
+
+(* --------------------------------------------------------------------- *)
+
+let undots x =
+ match unwrap x with
+ DOTS e -> e
+ | CIRCLES e -> e
+ | STARS e -> e
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* For minus fragment, checks that all of the identifier metavariables that
+are used are not declared as fresh, and check that all declared variables
+are used. For plus fragment, just check that the variables declared as
+fresh are used. What is the issue about error variables? (don't remember) *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module V0 = Visitor_ast0
+
+(* all fresh identifiers *)
+let fresh_table = (Hashtbl.create(50) : ((string * string), unit) Hashtbl.t)
+
+let warning s = Printf.fprintf stderr "warning: %s\n" s
+
+let promote name = (name,(),Ast0.default_info(),(),None)
+
+(* --------------------------------------------------------------------- *)
+
+let find_loop table name =
+ let rec loop = function
+ [] -> raise Not_found
+ | x::xs -> (try Hashtbl.find x name with Not_found -> loop xs) in
+ loop table
+
+let check_table table minus (name,_,info,_,_) =
+ let rl = info.Ast0.line_start in
+ if minus
+ then
+ (try (find_loop table name) := true
+ with
+ Not_found ->
+ (try
+ Hashtbl.find fresh_table name;
+ let (_,name) = name in
+ failwith
+ (Printf.sprintf
+ "%d: unexpected use of a fresh identifier %s" rl name)
+ with Not_found -> ()))
+ else (try (find_loop table name) := true with Not_found -> ())
+
+let get_opt fn = Common.do_option fn
+
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots fn d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> List.iter fn x
+ | Ast0.CIRCLES(x) -> List.iter fn x
+ | Ast0.STARS(x) -> List.iter fn x
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+type context = ID | FIELD | FN | GLOBAL
+
+(* heuristic for distinguishing ifdef variables from undeclared metavariables*)
+let is_ifdef name =
+ String.length name > 2 && String.uppercase name = name
+
+let ident context old_metas table minus i =
+ match Ast0.unwrap i with
+ Ast0.Id((name,_,info,_,_) : string Ast0.mcode) ->
+ let rl = info.Ast0.line_start in
+ let err =
+ if List.exists (function x -> x = name) old_metas
+ && (minus || Ast0.get_mcodekind i = Ast0.PLUS)
+ then
+ begin
+ warning
+ (Printf.sprintf
+ "line %d: %s, previously declared as a metavariable, is used as an identifier" rl name);
+ true
+ end
+ else false in
+ (match context with
+ ID ->
+ if not (is_ifdef name) && minus && not err(* warn only once per id *)
+ then
+ warning
+ (Printf.sprintf "line %d: should %s be a metavariable?" rl name)
+ | _ -> ())
+ | Ast0.MetaId(name,_,_) -> check_table table minus name
+ | Ast0.MetaFunc(name,_,_) -> check_table table minus name
+ | Ast0.MetaLocalFunc(name,_,_) -> check_table table minus name
+ | Ast0.OptIdent(_) | Ast0.UniqueIdent(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let rec expression context old_metas table minus e =
+ match Ast0.unwrap e with
+ Ast0.Ident(id) ->
+ ident context old_metas table minus id
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ expression FN old_metas table minus fn;
+ dots (expression ID old_metas table minus) args
+ | Ast0.Assignment(left,op,right,_) ->
+ expression context old_metas table minus left;
+ expression ID old_metas table minus right
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ expression ID old_metas table minus exp1;
+ get_opt (expression ID old_metas table minus) exp2;
+ expression ID old_metas table minus exp3
+ | Ast0.Postfix(exp,op) ->
+ expression ID old_metas table minus exp
+ | Ast0.Infix(exp,op) ->
+ expression ID old_metas table minus exp
+ | Ast0.Unary(exp,op) ->
+ expression ID old_metas table minus exp
+ | Ast0.Binary(left,op,right) ->
+ expression ID old_metas table minus left;
+ expression ID old_metas table minus right
+ | Ast0.Paren(lp,exp,rp) ->
+ expression ID old_metas table minus exp
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ expression ID old_metas table minus exp1;
+ expression ID old_metas table minus exp2
+ | Ast0.RecordAccess(exp,pt,field) ->
+ expression ID old_metas table minus exp;
+ ident FIELD old_metas table minus field
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ expression ID old_metas table minus exp;
+ ident FIELD old_metas table minus field
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ typeC old_metas table minus ty; expression ID old_metas table minus exp
+ | Ast0.SizeOfExpr(szf,exp) -> expression ID old_metas table minus exp
+ | Ast0.SizeOfType(szf,lp,ty,rp) -> typeC old_metas table minus ty
+ | Ast0.TypeExp(ty) -> typeC old_metas table minus ty
+ | Ast0.MetaExpr(name,_,Some tys,_,_) ->
+ List.iter
+ (function x ->
+ match get_type_name x with
+ Some(ty) -> check_table table minus (promote ty)
+ | None -> ())
+ tys;
+ check_table table minus name
+ | Ast0.MetaExpr(name,_,_,_,_) | Ast0.MetaErr(name,_,_) ->
+ check_table table minus name
+ | Ast0.MetaExprList(name,None,_) ->
+ check_table table minus name
+ | Ast0.MetaExprList(name,Some lenname,_) ->
+ check_table table minus name;
+ check_table table minus lenname
+ | Ast0.DisjExpr(_,exps,_,_) ->
+ List.iter (expression ID old_metas table minus) exps
+ | Ast0.NestExpr(_,exp_dots,_,w,_) ->
+ dots (expression ID old_metas table minus) exp_dots;
+ get_opt (expression ID old_metas table minus) w
+ | Ast0.Edots(_,Some x) | Ast0.Ecircles(_,Some x) | Ast0.Estars(_,Some x) ->
+ expression ID old_metas table minus x
+ | _ -> () (* no metavariable subterms *)
+
+and get_type_name = function
+ Type_cocci.ConstVol(_,ty) | Type_cocci.Pointer(ty)
+ | Type_cocci.FunctionPointer(ty) | Type_cocci.Array(ty) -> get_type_name ty
+ | Type_cocci.MetaType(nm,_,_) -> Some nm
+ | _ -> None
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and typeC old_metas table minus t =
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> typeC old_metas table minus ty
+ | Ast0.Pointer(ty,star) -> typeC old_metas table minus ty
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ typeC old_metas table minus ty;
+ parameter_list old_metas table minus params
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ get_opt (typeC old_metas table minus) ty;
+ parameter_list old_metas table minus params
+ | Ast0.Array(ty,lb,size,rb) ->
+ typeC old_metas table minus ty;
+ get_opt (expression ID old_metas table minus) size
+ | Ast0.MetaType(name,_) ->
+ check_table table minus name
+ | Ast0.DisjType(_,types,_,_) ->
+ List.iter (typeC old_metas table minus) types
+ | Ast0.StructUnionName(su,Some id) -> ident GLOBAL old_metas table minus id
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ typeC old_metas table minus ty;
+ dots (declaration GLOBAL old_metas table minus) decls
+ | Ast0.OptType(ty) | Ast0.UniqueType(ty) ->
+ failwith "unexpected code"
+ | _ -> () (* no metavariable subterms *)
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and declaration context old_metas table minus d =
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ (match Ast0.unwrap ini with
+ Ast0.InitExpr exp ->
+ typeC old_metas table minus ty;
+ ident context old_metas table minus id;
+ expression ID old_metas table minus exp
+ | _ ->
+ (*
+ if minus
+ then
+ failwith "complex initializer specification not allowed in - code"
+ else*)
+ (typeC old_metas table minus ty;
+ ident context old_metas table minus id;
+ initialiser old_metas table minus ini))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ typeC old_metas table minus ty; ident context old_metas table minus id
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ ident ID old_metas table minus name;
+ dots (expression ID old_metas table minus) args
+ | Ast0.TyDecl(ty,sem) -> typeC old_metas table minus ty
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ typeC old_metas table minus ty;
+ typeC old_metas table minus id
+ | Ast0.DisjDecl(_,decls,_,_) ->
+ List.iter (declaration ID old_metas table minus) decls
+ | Ast0.Ddots(_,Some x) -> declaration ID old_metas table minus x
+ | Ast0.Ddots(_,None) -> ()
+ | Ast0.OptDecl(_) | Ast0.UniqueDecl(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and initialiser old_metas table minus ini =
+ match Ast0.unwrap ini with
+ Ast0.InitExpr(exp) -> expression ID old_metas table minus exp
+ | Ast0.InitList(lb,initlist,rb) ->
+ dots (initialiser old_metas table minus) initlist
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ ident FIELD old_metas table minus name;
+ initialiser old_metas table minus ini
+ | Ast0.InitGccName(name,eq,ini) ->
+ ident FIELD old_metas table minus name;
+ initialiser old_metas table minus ini
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ expression ID old_metas table minus exp;
+ initialiser old_metas table minus ini
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ expression ID old_metas table minus exp1;
+ expression ID old_metas table minus exp2;
+ initialiser old_metas table minus ini
+ | Ast0.Idots(_,Some x) -> initialiser old_metas table minus x
+ | Ast0.OptIni(_) | Ast0.UniqueIni(_) ->
+ failwith "unexpected code"
+ | _ -> () (* no metavariable subterms *)
+
+and initialiser_list old_metas table minus =
+ dots (initialiser old_metas table minus)
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef old_metas table minus param =
+ match Ast0.unwrap param with
+ Ast0.Param(ty,id) ->
+ get_opt (ident ID old_metas table minus) id;
+ typeC old_metas table minus ty
+ | Ast0.MetaParam(name,_) ->
+ check_table table minus name
+ | Ast0.MetaParamList(name,None,_) ->
+ check_table table minus name
+ | Ast0.MetaParamList(name,Some lenname,_) ->
+ check_table table minus name;
+ check_table table minus lenname
+ | _ -> () (* no metavariable subterms *)
+
+and parameter_list old_metas table minus =
+ dots (parameterTypeDef old_metas table minus)
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and statement old_metas table minus s =
+ match Ast0.unwrap s with
+ Ast0.Decl(_,decl) -> declaration ID old_metas table minus decl
+ | Ast0.Seq(lbrace,body,rbrace) -> dots (statement old_metas table minus) body
+ | Ast0.ExprStatement(exp,sem) -> expression ID old_metas table minus exp
+ | Ast0.IfThen(iff,lp,exp,rp,branch,_) ->
+ expression ID old_metas table minus exp;
+ statement old_metas table minus branch
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,_) ->
+ expression ID old_metas table minus exp;
+ statement old_metas table minus branch1;
+ statement old_metas table minus branch2
+ | Ast0.While(wh,lp,exp,rp,body,_) ->
+ expression ID old_metas table minus exp;
+ statement old_metas table minus body
+ | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
+ statement old_metas table minus body;
+ expression ID old_metas table minus exp
+ | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,_) ->
+ get_opt (expression ID old_metas table minus) exp1;
+ get_opt (expression ID old_metas table minus) exp2;
+ get_opt (expression ID old_metas table minus) exp3;
+ statement old_metas table minus body
+ | Ast0.Iterator(nm,lp,args,rp,body,_) ->
+ ident ID old_metas table minus nm;
+ dots (expression ID old_metas table minus) args;
+ statement old_metas table minus body
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ expression ID old_metas table minus exp;
+ dots (case_line old_metas table minus) cases
+ | Ast0.ReturnExpr(ret,exp,sem) -> expression ID old_metas table minus exp
+ | Ast0.MetaStmt(name,_) -> check_table table minus name
+ | Ast0.MetaStmtList(name,_) -> check_table table minus name
+ | Ast0.Exp(exp) -> expression ID old_metas table minus exp
+ | Ast0.TopExp(exp) -> expression ID old_metas table minus exp
+ | Ast0.Ty(ty) -> typeC old_metas table minus ty
+ | Ast0.Disj(_,rule_elem_dots_list,_,_) ->
+ List.iter (dots (statement old_metas table minus)) rule_elem_dots_list
+ | Ast0.Nest(_,rule_elem_dots,_,w,_) ->
+ dots (statement old_metas table minus) rule_elem_dots;
+ List.iter (whencode (dots (statement old_metas table minus))
+ (statement old_metas table minus))
+ w
+ | Ast0.Dots(_,x) | Ast0.Circles(_,x) | Ast0.Stars(_,x) ->
+ List.iter
+ (whencode (dots (statement old_metas table minus))
+ (statement old_metas table minus)) x
+ | Ast0.FunDecl(_,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ ident FN old_metas table minus name;
+ List.iter (fninfo old_metas table minus) fi;
+ parameter_list old_metas table minus params;
+ dots (statement old_metas table minus) body
+ | Ast0.Include(inc,s) -> () (* no metavariables possible *)
+ | Ast0.Define(def,id,_,body) ->
+ ident GLOBAL old_metas table minus id;
+ dots (statement old_metas table minus) body
+ | Ast0.Goto(_,i,_) -> ident ID old_metas table minus i
+ | _ -> () (* no metavariable subterms *)
+
+and fninfo old_metas table minus = function
+ Ast0.FStorage(stg) -> ()
+ | Ast0.FType(ty) -> typeC old_metas table minus ty
+ | Ast0.FInline(inline) -> ()
+ | Ast0.FAttr(attr) -> ()
+
+and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> notfn a
+ | Ast0.WhenAlways a -> alwaysfn a
+ | Ast0.WhenModifier(_) -> ()
+
+and case_line old_metas table minus c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ dots (statement old_metas table minus) code
+ | Ast0.Case(case,exp,colon,code) ->
+ dots (statement old_metas table minus) code
+ | Ast0.OptCase(case) -> failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Rules *)
+
+let top_level old_metas table minus t =
+ match Ast0.unwrap t with
+ Ast0.DECL(stmt) -> statement old_metas table minus stmt
+ | Ast0.CODE(stmt_dots) -> dots (statement old_metas table minus) stmt_dots
+ | Ast0.ERRORWORDS(exps) ->
+ List.iter (expression FN old_metas table minus) exps
+ | _ -> () (* no metavariables possible *)
+
+let rule old_metas table minus rules =
+ List.iter (top_level old_metas table minus) rules
+
+(* --------------------------------------------------------------------- *)
+
+let positions table rules =
+ let mcode x =
+ match Ast0.get_pos x with
+ Ast0.MetaPos(name,constraints,_) ->
+ let pos = Ast0.unwrap_mcode name in
+ (find_loop table pos) := true
+ | _ -> () in
+ let option_default = () in
+ let bind x y = () in
+ let donothing r k e = k e in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing in
+
+ List.iter fn.V0.combiner_top_level rules
+
+let dup_positions rules =
+ let mcode x =
+ match Ast0.get_pos x with
+ Ast0.MetaPos(name,constraints,_) ->
+ let pos = Ast0.unwrap_mcode name in [pos]
+ | _ -> [] in
+ let option_default = [] in
+ let bind x y = x@y in
+
+ (* Case for everything that has a disj.
+ Note, no positions on ( | ) of a disjunction, so no need to recurse on
+ these. *)
+
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjExpr(_,explist,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_expression explist)
+ | _ -> k e in
+
+ let typeC r k e = (* not sure relevent because "only after iso" *)
+ match Ast0.unwrap e with
+ Ast0.DisjType(_,types,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_typeC types)
+ | _ -> k e in
+
+ let declaration r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjDecl(_,decls,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_declaration decls)
+ | _ -> k e in
+
+ let statement r k e =
+ match Ast0.unwrap e with
+ Ast0.Disj(_,stmts,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_statement_dots stmts)
+ | _ -> k e in
+
+ let donothing r k e = k e in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing expression typeC donothing donothing declaration statement
+ donothing donothing in
+
+ let res =
+ List.sort compare
+ (List.fold_left Common.union_set option_default
+ (List.map fn.V0.combiner_top_level rules)) in
+ let rec loop = function
+ [] | [_] -> ()
+ | ((rule,name) as x)::y::_ when x = y ->
+ failwith (Printf.sprintf "duplicate use of %s.%s" rule name)
+ | _::xs -> loop xs in
+ loop res
+
+(* --------------------------------------------------------------------- *)
+
+let make_table l =
+ let table =
+ (Hashtbl.create(List.length l) :
+ ((string * string), bool ref) Hashtbl.t) in
+ List.iter
+ (function x -> Hashtbl.add table (Ast.get_meta_name x) (ref false)) l;
+ table
+
+let add_to_fresh_table l =
+ List.iter
+ (function x ->
+ let name = Ast.get_meta_name x in Hashtbl.replace fresh_table name ())
+ l
+
+let check_all_marked rname err table after_err =
+ Hashtbl.iter
+ (function name ->
+ function (cell) ->
+ if not (!cell)
+ then
+ let (_,name) = name in
+ warning
+ (Printf.sprintf "%s: %s %s not used %s" rname err name after_err))
+ table
+
+let check_meta rname old_metas inherited_metavars metavars minus plus =
+ let old_metas =
+ List.map (function (_,x) -> x) (List.map Ast.get_meta_name old_metas) in
+ let (fresh,other) =
+ List.partition (function Ast.MetaFreshIdDecl(_,_) -> true | _ -> false)
+ metavars in
+ let (err,other) =
+ List.partition (function Ast.MetaErrDecl(_,_) -> true | _ -> false)
+ other in
+ let (ierr,iother) =
+ List.partition (function Ast.MetaErrDecl(_,_) -> true | _ -> false)
+ inherited_metavars in
+ let fresh_table = make_table fresh in
+ let err_table = make_table (err@ierr) in
+ let other_table = make_table other in
+ let iother_table = make_table iother in
+ add_to_fresh_table fresh;
+ rule old_metas [iother_table;other_table;err_table] true minus;
+ positions [iother_table;other_table] minus;
+ dup_positions minus;
+ check_all_marked rname "metavariable" other_table "in the - or context code";
+ rule old_metas [iother_table;fresh_table;err_table] false plus;
+ check_all_marked rname "fresh identifier metavariable" iother_table
+ "in the -, +, or context code";
+ check_all_marked rname "metavariable" fresh_table "in the + code";
+ check_all_marked rname "error metavariable" err_table ""
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* For minus fragment, checks that all of the identifier metavariables that
+are used are not declared as fresh, and check that all declared variables
+are used. For plus fragment, just check that the variables declared as
+fresh are used. What is the issue about error variables? (don't remember) *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module V0 = Visitor_ast0
+
+(* all fresh identifiers *)
+let fresh_table = (Hashtbl.create(50) : ((string * string), unit) Hashtbl.t)
+
+let warning s = Printf.fprintf stderr "warning: %s\n" s
+
+let promote name = (name,(),Ast0.default_info(),(),None)
+
+(* --------------------------------------------------------------------- *)
+
+let find_loop table name =
+ let rec loop = function
+ [] -> raise Not_found
+ | x::xs -> (try Hashtbl.find x name with Not_found -> loop xs) in
+ loop table
+
+let check_table table minus (name,_,info,_,_) =
+ let rl = info.Ast0.line_start in
+ if minus
+ then
+ (try (find_loop table name) := true
+ with
+ Not_found ->
+ (try
+ Hashtbl.find fresh_table name;
+ let (_,name) = name in
+ failwith
+ (Printf.sprintf
+ "%d: unexpected use of a fresh identifier %s" rl name)
+ with Not_found -> ()))
+ else (try (find_loop table name) := true with Not_found -> ())
+
+let get_opt fn = Common.do_option fn
+
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots fn d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(x) -> List.iter fn x
+ | Ast0.CIRCLES(x) -> List.iter fn x
+ | Ast0.STARS(x) -> List.iter fn x
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+type context = ID | FIELD | FN | GLOBAL
+
+(* heuristic for distinguishing ifdef variables from undeclared metavariables*)
+let is_ifdef name =
+ String.length name > 2 && String.uppercase name = name
+
+let ident context old_metas table minus i =
+ match Ast0.unwrap i with
+ Ast0.Id((name,_,info,_,_) : string Ast0.mcode) ->
+ let rl = info.Ast0.line_start in
+ let err =
+ if List.exists (function x -> x = name) old_metas
+ && (minus || Ast0.get_mcodekind i = Ast0.PLUS)
+ then
+ begin
+ warning
+ (Printf.sprintf
+ "line %d: %s, previously declared as a metavariable, is used as an identifier" rl name);
+ true
+ end
+ else false in
+ (match context with
+ ID ->
+ if not (is_ifdef name) && minus && not err(* warn only once per id *)
+ then
+ warning
+ (Printf.sprintf "line %d: should %s be a metavariable?" rl name)
+ | _ -> ())
+ | Ast0.MetaId(name,_,_) -> check_table table minus name
+ | Ast0.MetaFunc(name,_,_) -> check_table table minus name
+ | Ast0.MetaLocalFunc(name,_,_) -> check_table table minus name
+ | Ast0.OptIdent(_) | Ast0.UniqueIdent(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let rec expression context old_metas table minus e =
+ match Ast0.unwrap e with
+ Ast0.Ident(id) ->
+ ident context old_metas table minus id
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ expression FN old_metas table minus fn;
+ dots (expression ID old_metas table minus) args
+ | Ast0.Assignment(left,op,right,_) ->
+ expression context old_metas table minus left;
+ expression ID old_metas table minus right
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ expression ID old_metas table minus exp1;
+ get_opt (expression ID old_metas table minus) exp2;
+ expression ID old_metas table minus exp3
+ | Ast0.Postfix(exp,op) ->
+ expression ID old_metas table minus exp
+ | Ast0.Infix(exp,op) ->
+ expression ID old_metas table minus exp
+ | Ast0.Unary(exp,op) ->
+ expression ID old_metas table minus exp
+ | Ast0.Binary(left,op,right) ->
+ expression ID old_metas table minus left;
+ expression ID old_metas table minus right
+ | Ast0.Paren(lp,exp,rp) ->
+ expression ID old_metas table minus exp
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ expression ID old_metas table minus exp1;
+ expression ID old_metas table minus exp2
+ | Ast0.RecordAccess(exp,pt,field) ->
+ expression ID old_metas table minus exp;
+ ident FIELD old_metas table minus field
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ expression ID old_metas table minus exp;
+ ident FIELD old_metas table minus field
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ typeC old_metas table minus ty; expression ID old_metas table minus exp
+ | Ast0.SizeOfExpr(szf,exp) -> expression ID old_metas table minus exp
+ | Ast0.SizeOfType(szf,lp,ty,rp) -> typeC old_metas table minus ty
+ | Ast0.TypeExp(ty) -> typeC old_metas table minus ty
+ | Ast0.MetaExpr(name,_,Some tys,_,_) ->
+ List.iter
+ (function x ->
+ match get_type_name x with
+ Some(ty) -> check_table table minus (promote ty)
+ | None -> ())
+ tys;
+ check_table table minus name
+ | Ast0.MetaExpr(name,_,_,_,_) | Ast0.MetaErr(name,_,_) ->
+ check_table table minus name
+ | Ast0.MetaExprList(name,None,_) ->
+ check_table table minus name
+ | Ast0.MetaExprList(name,Some lenname,_) ->
+ check_table table minus name;
+ check_table table minus lenname
+ | Ast0.DisjExpr(_,exps,_,_) ->
+ List.iter (expression ID old_metas table minus) exps
+ | Ast0.NestExpr(_,exp_dots,_,w,_) ->
+ dots (expression ID old_metas table minus) exp_dots;
+ get_opt (expression ID old_metas table minus) w
+ | Ast0.Edots(_,Some x) | Ast0.Ecircles(_,Some x) | Ast0.Estars(_,Some x) ->
+ expression ID old_metas table minus x
+ | _ -> () (* no metavariable subterms *)
+
+and get_type_name = function
+ Type_cocci.ConstVol(_,ty) | Type_cocci.Pointer(ty)
+ | Type_cocci.FunctionPointer(ty) | Type_cocci.Array(ty) -> get_type_name ty
+ | Type_cocci.MetaType(nm,_,_) -> Some nm
+ | _ -> None
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and typeC old_metas table minus t =
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> typeC old_metas table minus ty
+ | Ast0.Pointer(ty,star) -> typeC old_metas table minus ty
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ typeC old_metas table minus ty;
+ parameter_list old_metas table minus params
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ get_opt (typeC old_metas table minus) ty;
+ parameter_list old_metas table minus params
+ | Ast0.Array(ty,lb,size,rb) ->
+ typeC old_metas table minus ty;
+ get_opt (expression ID old_metas table minus) size
+ | Ast0.MetaType(name,_) ->
+ check_table table minus name
+ | Ast0.DisjType(_,types,_,_) ->
+ List.iter (typeC old_metas table minus) types
+ | Ast0.StructUnionName(su,Some id) -> ident GLOBAL old_metas table minus id
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ typeC old_metas table minus ty;
+ dots (declaration GLOBAL old_metas table minus) decls
+ | Ast0.OptType(ty) | Ast0.UniqueType(ty) ->
+ failwith "unexpected code"
+ | _ -> () (* no metavariable subterms *)
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and declaration context old_metas table minus d =
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ (match Ast0.unwrap ini with
+ Ast0.InitExpr exp ->
+ typeC old_metas table minus ty;
+ ident context old_metas table minus id;
+ expression ID old_metas table minus exp
+ | _ ->
+ (*
+ if minus
+ then
+ failwith "complex initializer specification not allowed in - code"
+ else*)
+ (typeC old_metas table minus ty;
+ ident context old_metas table minus id;
+ initialiser old_metas table minus ini))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ typeC old_metas table minus ty; ident context old_metas table minus id
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ ident ID old_metas table minus name;
+ dots (expression ID old_metas table minus) args
+ | Ast0.TyDecl(ty,sem) -> typeC old_metas table minus ty
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ typeC old_metas table minus ty;
+ typeC old_metas table minus id
+ | Ast0.DisjDecl(_,decls,_,_) ->
+ List.iter (declaration ID old_metas table minus) decls
+ | Ast0.Ddots(_,Some x) -> declaration ID old_metas table minus x
+ | Ast0.Ddots(_,None) -> ()
+ | Ast0.OptDecl(_) | Ast0.UniqueDecl(_) ->
+ failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and initialiser old_metas table minus ini =
+ match Ast0.unwrap ini with
+ Ast0.InitExpr(exp) -> expression ID old_metas table minus exp
+ | Ast0.InitList(lb,initlist,rb) ->
+ dots (initialiser old_metas table minus) initlist
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ ident FIELD old_metas table minus name;
+ initialiser old_metas table minus ini
+ | Ast0.InitGccName(name,eq,ini) ->
+ ident FIELD old_metas table minus name;
+ initialiser old_metas table minus ini
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ expression ID old_metas table minus exp;
+ initialiser old_metas table minus ini
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ expression ID old_metas table minus exp1;
+ expression ID old_metas table minus exp2;
+ initialiser old_metas table minus ini
+ | Ast0.Idots(_,Some x) -> initialiser old_metas table minus x
+ | Ast0.OptIni(_) | Ast0.UniqueIni(_) ->
+ failwith "unexpected code"
+ | _ -> () (* no metavariable subterms *)
+
+and initialiser_list old_metas table minus =
+ dots (initialiser old_metas table minus)
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef old_metas table minus param =
+ match Ast0.unwrap param with
+ Ast0.Param(ty,id) ->
+ get_opt (ident ID old_metas table minus) id;
+ typeC old_metas table minus ty
+ | Ast0.MetaParam(name,_) ->
+ check_table table minus name
+ | Ast0.MetaParamList(name,None,_) ->
+ check_table table minus name
+ | Ast0.MetaParamList(name,Some lenname,_) ->
+ check_table table minus name;
+ check_table table minus lenname
+ | _ -> () (* no metavariable subterms *)
+
+and parameter_list old_metas table minus =
+ dots (parameterTypeDef old_metas table minus)
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and statement old_metas table minus s =
+ match Ast0.unwrap s with
+ Ast0.Decl(_,decl) -> declaration ID old_metas table minus decl
+ | Ast0.Seq(lbrace,body,rbrace) -> dots (statement old_metas table minus) body
+ | Ast0.ExprStatement(exp,sem) -> expression ID old_metas table minus exp
+ | Ast0.IfThen(iff,lp,exp,rp,branch,_) ->
+ expression ID old_metas table minus exp;
+ statement old_metas table minus branch
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,_) ->
+ expression ID old_metas table minus exp;
+ statement old_metas table minus branch1;
+ statement old_metas table minus branch2
+ | Ast0.While(wh,lp,exp,rp,body,_) ->
+ expression ID old_metas table minus exp;
+ statement old_metas table minus body
+ | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
+ statement old_metas table minus body;
+ expression ID old_metas table minus exp
+ | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,_) ->
+ get_opt (expression ID old_metas table minus) exp1;
+ get_opt (expression ID old_metas table minus) exp2;
+ get_opt (expression ID old_metas table minus) exp3;
+ statement old_metas table minus body
+ | Ast0.Iterator(nm,lp,args,rp,body,_) ->
+ ident ID old_metas table minus nm;
+ dots (expression ID old_metas table minus) args;
+ statement old_metas table minus body
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ expression ID old_metas table minus exp;
+ dots (case_line old_metas table minus) cases
+ | Ast0.ReturnExpr(ret,exp,sem) -> expression ID old_metas table minus exp
+ | Ast0.MetaStmt(name,_) -> check_table table minus name
+ | Ast0.MetaStmtList(name,_) -> check_table table minus name
+ | Ast0.Exp(exp) -> expression ID old_metas table minus exp
+ | Ast0.TopExp(exp) -> expression ID old_metas table minus exp
+ | Ast0.Ty(ty) -> typeC old_metas table minus ty
+ | Ast0.Disj(_,rule_elem_dots_list,_,_) ->
+ List.iter (dots (statement old_metas table minus)) rule_elem_dots_list
+ | Ast0.Nest(_,rule_elem_dots,_,w,_) ->
+ dots (statement old_metas table minus) rule_elem_dots;
+ List.iter (whencode (dots (statement old_metas table minus))
+ (statement old_metas table minus)
+ (expression ID old_metas table minus))
+ w
+ | Ast0.Dots(_,x) | Ast0.Circles(_,x) | Ast0.Stars(_,x) ->
+ List.iter
+ (whencode (dots (statement old_metas table minus))
+ (statement old_metas table minus)
+ (expression ID old_metas table minus)) x
+ | Ast0.FunDecl(_,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ ident FN old_metas table minus name;
+ List.iter (fninfo old_metas table minus) fi;
+ parameter_list old_metas table minus params;
+ dots (statement old_metas table minus) body
+ | Ast0.Include(inc,s) -> () (* no metavariables possible *)
+ | Ast0.Define(def,id,_,body) ->
+ ident GLOBAL old_metas table minus id;
+ dots (statement old_metas table minus) body
+ | Ast0.Goto(_,i,_) -> ident ID old_metas table minus i
+ | _ -> () (* no metavariable subterms *)
+
+and fninfo old_metas table minus = function
+ Ast0.FStorage(stg) -> ()
+ | Ast0.FType(ty) -> typeC old_metas table minus ty
+ | Ast0.FInline(inline) -> ()
+ | Ast0.FAttr(attr) -> ()
+
+and whencode notfn alwaysfn expression = function
+ Ast0.WhenNot a -> notfn a
+ | Ast0.WhenAlways a -> alwaysfn a
+ | Ast0.WhenModifier(_) -> ()
+ | Ast0.WhenNotTrue a -> expression a
+ | Ast0.WhenNotFalse a -> expression a
+
+and case_line old_metas table minus c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ dots (statement old_metas table minus) code
+ | Ast0.Case(case,exp,colon,code) ->
+ dots (statement old_metas table minus) code
+ | Ast0.OptCase(case) -> failwith "unexpected code"
+
+(* --------------------------------------------------------------------- *)
+(* Rules *)
+
+let top_level old_metas table minus t =
+ match Ast0.unwrap t with
+ Ast0.DECL(stmt) -> statement old_metas table minus stmt
+ | Ast0.CODE(stmt_dots) -> dots (statement old_metas table minus) stmt_dots
+ | Ast0.ERRORWORDS(exps) ->
+ List.iter (expression FN old_metas table minus) exps
+ | _ -> () (* no metavariables possible *)
+
+let rule old_metas table minus rules =
+ List.iter (top_level old_metas table minus) rules
+
+(* --------------------------------------------------------------------- *)
+
+let positions table rules =
+ let mcode x =
+ match Ast0.get_pos x with
+ Ast0.MetaPos(name,constraints,_) ->
+ let pos = Ast0.unwrap_mcode name in
+ (find_loop table pos) := true
+ | _ -> () in
+ let option_default = () in
+ let bind x y = () in
+ let donothing r k e = k e in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing in
+
+ List.iter fn.V0.combiner_top_level rules
+
+let dup_positions rules =
+ let mcode x =
+ match Ast0.get_pos x with
+ Ast0.MetaPos(name,constraints,_) ->
+ let pos = Ast0.unwrap_mcode name in [pos]
+ | _ -> [] in
+ let option_default = [] in
+ let bind x y = x@y in
+
+ (* Case for everything that has a disj.
+ Note, no positions on ( | ) of a disjunction, so no need to recurse on
+ these. *)
+
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjExpr(_,explist,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_expression explist)
+ | _ -> k e in
+
+ let typeC r k e = (* not sure relevent because "only after iso" *)
+ match Ast0.unwrap e with
+ Ast0.DisjType(_,types,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_typeC types)
+ | _ -> k e in
+
+ let declaration r k e =
+ match Ast0.unwrap e with
+ Ast0.DisjDecl(_,decls,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_declaration decls)
+ | _ -> k e in
+
+ let statement r k e =
+ match Ast0.unwrap e with
+ Ast0.Disj(_,stmts,_,_) ->
+ List.fold_left Common.union_set option_default
+ (List.map r.V0.combiner_statement_dots stmts)
+ | _ -> k e in
+
+ let donothing r k e = k e in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing expression typeC donothing donothing declaration statement
+ donothing donothing in
+
+ let res =
+ List.sort compare
+ (List.fold_left Common.union_set option_default
+ (List.map fn.V0.combiner_top_level rules)) in
+ let rec loop = function
+ [] | [_] -> ()
+ | ((rule,name) as x)::y::_ when x = y ->
+ failwith (Printf.sprintf "duplicate use of %s.%s" rule name)
+ | _::xs -> loop xs in
+ loop res
+
+(* --------------------------------------------------------------------- *)
+
+let make_table l =
+ let table =
+ (Hashtbl.create(List.length l) :
+ ((string * string), bool ref) Hashtbl.t) in
+ List.iter
+ (function x -> Hashtbl.add table (Ast.get_meta_name x) (ref false)) l;
+ table
+
+let add_to_fresh_table l =
+ List.iter
+ (function x ->
+ let name = Ast.get_meta_name x in Hashtbl.replace fresh_table name ())
+ l
+
+let check_all_marked rname err table after_err =
+ Hashtbl.iter
+ (function name ->
+ function (cell) ->
+ if not (!cell)
+ then
+ let (_,name) = name in
+ warning
+ (Printf.sprintf "%s: %s %s not used %s" rname err name after_err))
+ table
+
+let check_meta rname old_metas inherited_metavars metavars minus plus =
+ let old_metas =
+ List.map (function (_,x) -> x) (List.map Ast.get_meta_name old_metas) in
+ let (fresh,other) =
+ List.partition (function Ast.MetaFreshIdDecl(_,_) -> true | _ -> false)
+ metavars in
+ let (err,other) =
+ List.partition (function Ast.MetaErrDecl(_,_) -> true | _ -> false)
+ other in
+ let (ierr,iother) =
+ List.partition (function Ast.MetaErrDecl(_,_) -> true | _ -> false)
+ inherited_metavars in
+ let fresh_table = make_table fresh in
+ let err_table = make_table (err@ierr) in
+ let other_table = make_table other in
+ let iother_table = make_table iother in
+ add_to_fresh_table fresh;
+ rule old_metas [iother_table;other_table;err_table] true minus;
+ positions [iother_table;other_table] minus;
+ dup_positions minus;
+ check_all_marked rname "metavariable" other_table "in the - or context code";
+ rule old_metas [iother_table;fresh_table;err_table] false plus;
+ check_all_marked rname "fresh identifier metavariable" iother_table
+ "in the -, +, or context code";
+ check_all_marked rname "metavariable" fresh_table "in the + code";
+ check_all_marked rname "error metavariable" err_table ""
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Computes starting and ending logical lines for statements and
+expressions. every node gets an index as well. *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+
+(* --------------------------------------------------------------------- *)
+(* Result *)
+
+let mkres x e left right =
+ let lstart = Ast0.get_info left in
+ let lend = Ast0.get_info right in
+ let info =
+ { Ast0.line_start = lstart.Ast0.line_start;
+ Ast0.line_end = lend.Ast0.line_end;
+ Ast0.logical_start = lstart.Ast0.logical_start;
+ Ast0.logical_end = lend.Ast0.logical_end;
+ Ast0.attachable_start = lstart.Ast0.attachable_start;
+ Ast0.attachable_end = lend.Ast0.attachable_end;
+ Ast0.mcode_start = lstart.Ast0.mcode_start;
+ Ast0.mcode_end = lend.Ast0.mcode_end;
+ Ast0.column = lstart.Ast0.column;
+ Ast0.offset = lstart.Ast0.offset;
+ (* only for tokens, not inherited upwards *)
+ Ast0.strings_before = []; Ast0.strings_after = []} in
+ {x with Ast0.node = e; Ast0.info = info}
+
+let mkmultires x e left right (astart,start_mcodes) (aend,end_mcodes) =
+ let lstart = Ast0.get_info left in
+ let lend = Ast0.get_info right in
+ let info =
+ { Ast0.line_start = lstart.Ast0.line_start;
+ Ast0.line_end = lend.Ast0.line_end;
+ Ast0.logical_start = lstart.Ast0.logical_start;
+ Ast0.logical_end = lend.Ast0.logical_end;
+ Ast0.attachable_start = astart;
+ Ast0.attachable_end = aend;
+ Ast0.mcode_start = start_mcodes;
+ Ast0.mcode_end = end_mcodes;
+ Ast0.column = lstart.Ast0.column;
+ Ast0.offset = lstart.Ast0.offset;
+ (* only for tokens, not inherited upwards *)
+ Ast0.strings_before = []; Ast0.strings_after = [] } in
+ {x with Ast0.node = e; Ast0.info = info}
+
+(* --------------------------------------------------------------------- *)
+
+let get_option fn = function
+ None -> None
+ | Some x -> Some (fn x)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Mcode *)
+
+let promote_mcode (_,_,info,mcodekind,_) =
+ let new_info =
+ {info with
+ Ast0.mcode_start = [mcodekind]; Ast0.mcode_end = [mcodekind]} in
+ {(Ast0.wrap ()) with Ast0.info = new_info; Ast0.mcodekind = ref mcodekind}
+
+let promote_mcode_plus_one (_,_,info,mcodekind,_) =
+ let new_info =
+ {info with
+ Ast0.line_start = info.Ast0.line_start + 1;
+ Ast0.logical_start = info.Ast0.logical_start + 1;
+ Ast0.line_end = info.Ast0.line_end + 1;
+ Ast0.logical_end = info.Ast0.logical_end + 1;
+ Ast0.mcode_start = [mcodekind]; Ast0.mcode_end = [mcodekind]} in
+ {(Ast0.wrap ()) with Ast0.info = new_info; Ast0.mcodekind = ref mcodekind}
+
+let promote_to_statement stm mcodekind =
+ let info = Ast0.get_info stm in
+ let new_info =
+ {info with
+ Ast0.logical_start = info.Ast0.logical_end;
+ Ast0.line_start = info.Ast0.line_end;
+ Ast0.mcode_start = [mcodekind]; Ast0.mcode_end = [mcodekind];
+ Ast0.attachable_start = true; Ast0.attachable_end = true} in
+ {(Ast0.wrap ()) with Ast0.info = new_info; Ast0.mcodekind = ref mcodekind}
+
+let promote_to_statement_start stm mcodekind =
+ let info = Ast0.get_info stm in
+ let new_info =
+ {info with
+ Ast0.logical_end = info.Ast0.logical_start;
+ Ast0.line_end = info.Ast0.line_start;
+ Ast0.mcode_start = [mcodekind]; Ast0.mcode_end = [mcodekind];
+ Ast0.attachable_start = true; Ast0.attachable_end = true} in
+ {(Ast0.wrap ()) with Ast0.info = new_info; Ast0.mcodekind = ref mcodekind}
+
+(* mcode is good by default *)
+let bad_mcode (t,a,info,mcodekind,pos) =
+ let new_info =
+ {info with Ast0.attachable_start = false; Ast0.attachable_end = false} in
+ (t,a,new_info,mcodekind,pos)
+
+let get_all_start_info l =
+ (List.for_all (function x -> (Ast0.get_info x).Ast0.attachable_start) l,
+ List.concat (List.map (function x -> (Ast0.get_info x).Ast0.mcode_start) l))
+
+let get_all_end_info l =
+ (List.for_all (function x -> (Ast0.get_info x).Ast0.attachable_end) l,
+ List.concat (List.map (function x -> (Ast0.get_info x).Ast0.mcode_end) l))
+
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+(* for the logline classification and the mcode field, on both sides, skip
+over initial minus dots, as they don't contribute anything *)
+let dot_list is_dots fn = function
+ [] -> failwith "dots should not be empty"
+ | l ->
+ let get_node l fn =
+ let first = List.hd l in
+ let chosen =
+ match (is_dots first, l) with (true,_::x::_) -> x | _ -> first in
+ (* get the logline decorator and the mcodekind of the chosen node *)
+ fn (Ast0.get_info chosen) in
+ let forward = List.map fn l in
+ let backward = List.rev forward in
+ let (first_attachable,first_mcode) =
+ get_node forward
+ (function x -> (x.Ast0.attachable_start,x.Ast0.mcode_start)) in
+ let (last_attachable,last_mcode) =
+ get_node backward
+ (function x -> (x.Ast0.attachable_end,x.Ast0.mcode_end)) in
+ let first = List.hd forward in
+ let last = List.hd backward in
+ let first_info =
+ { (Ast0.get_info first) with
+ Ast0.attachable_start = first_attachable;
+ Ast0.mcode_start = first_mcode } in
+ let last_info =
+ { (Ast0.get_info last) with
+ Ast0.attachable_end = last_attachable;
+ Ast0.mcode_end = last_mcode } in
+ let first = Ast0.set_info first first_info in
+ let last = Ast0.set_info last last_info in
+ (forward,first,last)
+
+let dots is_dots prev fn d =
+ match (prev,Ast0.unwrap d) with
+ (Some prev,Ast0.DOTS([])) ->
+ mkres d (Ast0.DOTS []) prev prev
+ | (None,Ast0.DOTS([])) ->
+ Ast0.set_info d
+ {(Ast0.get_info d)
+ with Ast0.attachable_start = false; Ast0.attachable_end = false}
+ | (_,Ast0.DOTS(x)) ->
+ let (l,lstart,lend) = dot_list is_dots fn x in
+ mkres d (Ast0.DOTS l) lstart lend
+ | (_,Ast0.CIRCLES(x)) ->
+ let (l,lstart,lend) = dot_list is_dots fn x in
+ mkres d (Ast0.CIRCLES l) lstart lend
+ | (_,Ast0.STARS(x)) ->
+ let (l,lstart,lend) = dot_list is_dots fn x in
+ mkres d (Ast0.STARS l) lstart lend
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let rec ident i =
+ match Ast0.unwrap i with
+ Ast0.Id(name) as ui ->
+ let name = promote_mcode name in mkres i ui name name
+ | Ast0.MetaId(name,_,_)
+ | Ast0.MetaFunc(name,_,_) | Ast0.MetaLocalFunc(name,_,_) as ui ->
+ let name = promote_mcode name in mkres i ui name name
+ | Ast0.OptIdent(id) ->
+ let id = ident id in mkres i (Ast0.OptIdent(id)) id id
+ | Ast0.UniqueIdent(id) ->
+ let id = ident id in mkres i (Ast0.UniqueIdent(id)) id id
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let is_exp_dots e =
+ match Ast0.unwrap e with
+ Ast0.Edots(_,_) | Ast0.Ecircles(_,_) | Ast0.Estars(_,_) -> true
+ | _ -> false
+
+let rec expression e =
+ match Ast0.unwrap e with
+ Ast0.Ident(id) ->
+ let id = ident id in
+ mkres e (Ast0.Ident(id)) id id
+ | Ast0.Constant(const) as ue ->
+ let ln = promote_mcode const in
+ mkres e ue ln ln
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ let fn = expression fn in
+ let args = dots is_exp_dots (Some(promote_mcode lp)) expression args in
+ mkres e (Ast0.FunCall(fn,lp,args,rp)) fn (promote_mcode rp)
+ | Ast0.Assignment(left,op,right,simple) ->
+ let left = expression left in
+ let right = expression right in
+ mkres e (Ast0.Assignment(left,op,right,simple)) left right
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ let exp1 = expression exp1 in
+ let exp2 = get_option expression exp2 in
+ let exp3 = expression exp3 in
+ mkres e (Ast0.CondExpr(exp1,why,exp2,colon,exp3)) exp1 exp3
+ | Ast0.Postfix(exp,op) ->
+ let exp = expression exp in
+ mkres e (Ast0.Postfix(exp,op)) exp (promote_mcode op)
+ | Ast0.Infix(exp,op) ->
+ let exp = expression exp in
+ mkres e (Ast0.Infix(exp,op)) (promote_mcode op) exp
+ | Ast0.Unary(exp,op) ->
+ let exp = expression exp in
+ mkres e (Ast0.Unary(exp,op)) (promote_mcode op) exp
+ | Ast0.Binary(left,op,right) ->
+ let left = expression left in
+ let right = expression right in
+ mkres e (Ast0.Binary(left,op,right)) left right
+ | Ast0.Nested(left,op,right) ->
+ let left = expression left in
+ let right = expression right in
+ mkres e (Ast0.Nested(left,op,right)) left right
+ | Ast0.Paren(lp,exp,rp) ->
+ mkres e (Ast0.Paren(lp,expression exp,rp))
+ (promote_mcode lp) (promote_mcode rp)
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ let exp1 = expression exp1 in
+ let exp2 = expression exp2 in
+ mkres e (Ast0.ArrayAccess(exp1,lb,exp2,rb)) exp1 (promote_mcode rb)
+ | Ast0.RecordAccess(exp,pt,field) ->
+ let exp = expression exp in
+ let field = ident field in
+ mkres e (Ast0.RecordAccess(exp,pt,field)) exp field
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ let exp = expression exp in
+ let field = ident field in
+ mkres e (Ast0.RecordPtAccess(exp,ar,field)) exp field
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ let exp = expression exp in
+ mkres e (Ast0.Cast(lp,typeC ty,rp,exp)) (promote_mcode lp) exp
+ | Ast0.SizeOfExpr(szf,exp) ->
+ let exp = expression exp in
+ mkres e (Ast0.SizeOfExpr(szf,exp)) (promote_mcode szf) exp
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ mkres e (Ast0.SizeOfType(szf,lp,typeC ty,rp))
+ (promote_mcode szf) (promote_mcode rp)
+ | Ast0.TypeExp(ty) ->
+ let ty = typeC ty in mkres e (Ast0.TypeExp(ty)) ty ty
+ | Ast0.MetaErr(name,_,_) | Ast0.MetaExpr(name,_,_,_,_)
+ | Ast0.MetaExprList(name,_,_) as ue ->
+ let ln = promote_mcode name in mkres e ue ln ln
+ | Ast0.EComma(cm) ->
+ let cm = bad_mcode cm in
+ let ln = promote_mcode cm in
+ mkres e (Ast0.EComma(cm)) ln ln
+ | Ast0.DisjExpr(starter,exps,mids,ender) ->
+ let starter = bad_mcode starter in
+ let exps = List.map expression exps in
+ let mids = List.map bad_mcode mids in
+ let ender = bad_mcode ender in
+ mkmultires e (Ast0.DisjExpr(starter,exps,mids,ender))
+ (promote_mcode starter) (promote_mcode ender)
+ (get_all_start_info exps) (get_all_end_info exps)
+ | Ast0.NestExpr(starter,exp_dots,ender,whencode,multi) ->
+ let exp_dots = dots is_exp_dots None expression exp_dots in
+ let starter = bad_mcode starter in
+ let ender = bad_mcode ender in
+ mkres e (Ast0.NestExpr(starter,exp_dots,ender,whencode,multi))
+ (promote_mcode starter) (promote_mcode ender)
+ | Ast0.Edots(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres e (Ast0.Edots(dots,whencode)) ln ln
+ | Ast0.Ecircles(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres e (Ast0.Ecircles(dots,whencode)) ln ln
+ | Ast0.Estars(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres e (Ast0.Estars(dots,whencode)) ln ln
+ | Ast0.OptExp(exp) ->
+ let exp = expression exp in
+ mkres e (Ast0.OptExp(exp)) exp exp
+ | Ast0.UniqueExp(exp) ->
+ let exp = expression exp in
+ mkres e (Ast0.UniqueExp(exp)) exp exp
+
+and expression_dots x = dots is_exp_dots None expression x
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and typeC t =
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) ->
+ let ty = typeC ty in
+ mkres t (Ast0.ConstVol(cv,ty)) (promote_mcode cv) ty
+ | Ast0.BaseType(ty,None) as ut ->
+ mkres t ut (promote_mcode ty) (promote_mcode ty)
+ | Ast0.BaseType(ty,Some sgn) as ut ->
+ mkres t ut (promote_mcode sgn) (promote_mcode ty)
+ | Ast0.ImplicitInt(sgn) as ut ->
+ mkres t ut (promote_mcode sgn) (promote_mcode sgn)
+ | Ast0.Pointer(ty,star) ->
+ let ty = typeC ty in
+ mkres t (Ast0.Pointer(ty,star)) ty (promote_mcode star)
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ let ty = typeC ty in
+ let params = parameter_list (Some(promote_mcode lp2)) params in
+ mkres t (Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2))
+ ty (promote_mcode rp2)
+ | Ast0.FunctionType(Some ty,lp1,params,rp1) ->
+ let ty = typeC ty in
+ let params = parameter_list (Some(promote_mcode lp1)) params in
+ let res = Ast0.FunctionType(Some ty,lp1,params,rp1) in
+ mkres t res ty (promote_mcode rp1)
+ | Ast0.FunctionType(None,lp1,params,rp1) ->
+ let params = parameter_list (Some(promote_mcode lp1)) params in
+ let res = Ast0.FunctionType(None,lp1,params,rp1) in
+ mkres t res (promote_mcode lp1) (promote_mcode rp1)
+ | Ast0.Array(ty,lb,size,rb) ->
+ let ty = typeC ty in
+ mkres t (Ast0.Array(ty,lb,get_option expression size,rb))
+ ty (promote_mcode rb)
+ | Ast0.StructUnionName(kind,Some name) ->
+ let name = ident name in
+ mkres t (Ast0.StructUnionName(kind,Some name)) (promote_mcode kind) name
+ | Ast0.StructUnionName(kind,None) ->
+ let mc = promote_mcode kind in
+ mkres t (Ast0.StructUnionName(kind,None)) mc mc
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ let ty = typeC ty in
+ let decls =
+ dots is_decl_dots (Some(promote_mcode lb)) declaration decls in
+ mkres t (Ast0.StructUnionDef(ty,lb,decls,rb)) ty (promote_mcode rb)
+ | Ast0.TypeName(name) as ut ->
+ let ln = promote_mcode name in mkres t ut ln ln
+ | Ast0.MetaType(name,_) as ut ->
+ let ln = promote_mcode name in mkres t ut ln ln
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ let starter = bad_mcode starter in
+ let types = List.map typeC types in
+ let mids = List.map bad_mcode mids in
+ let ender = bad_mcode ender in
+ mkmultires t (Ast0.DisjType(starter,types,mids,ender))
+ (promote_mcode starter) (promote_mcode ender)
+ (get_all_start_info types) (get_all_end_info types)
+ | Ast0.OptType(ty) ->
+ let ty = typeC ty in mkres t (Ast0.OptType(ty)) ty ty
+ | Ast0.UniqueType(ty) ->
+ let ty = typeC ty in mkres t (Ast0.UniqueType(ty)) ty ty
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and is_decl_dots s =
+ match Ast0.unwrap s with
+ Ast0.Ddots(_,_) -> true
+ | _ -> false
+
+and declaration d =
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,exp,sem) ->
+ let ty = typeC ty in
+ let id = ident id in
+ let exp = initialiser exp in
+ (match stg with
+ None ->
+ mkres d (Ast0.Init(stg,ty,id,eq,exp,sem)) ty (promote_mcode sem)
+ | Some x ->
+ mkres d (Ast0.Init(stg,ty,id,eq,exp,sem))
+ (promote_mcode x) (promote_mcode sem))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ let ty = typeC ty in
+ let id = ident id in
+ (match stg with
+ None ->
+ mkres d (Ast0.UnInit(stg,ty,id,sem)) ty (promote_mcode sem)
+ | Some x ->
+ mkres d (Ast0.UnInit(stg,ty,id,sem))
+ (promote_mcode x) (promote_mcode sem))
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ let name = ident name in
+ let args = dots is_exp_dots (Some(promote_mcode lp)) expression args in
+ mkres d (Ast0.MacroDecl(name,lp,args,rp,sem)) name (promote_mcode sem)
+ | Ast0.TyDecl(ty,sem) ->
+ let ty = typeC ty in
+ mkres d (Ast0.TyDecl(ty,sem)) ty (promote_mcode sem)
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ let ty = typeC ty in
+ let id = typeC id in
+ mkres d (Ast0.Typedef(stg,ty,id,sem))
+ (promote_mcode stg) (promote_mcode sem)
+ | Ast0.DisjDecl(starter,decls,mids,ender) ->
+ let starter = bad_mcode starter in
+ let decls = List.map declaration decls in
+ let mids = List.map bad_mcode mids in
+ let ender = bad_mcode ender in
+ mkmultires d (Ast0.DisjDecl(starter,decls,mids,ender))
+ (promote_mcode starter) (promote_mcode ender)
+ (get_all_start_info decls) (get_all_end_info decls)
+ | Ast0.Ddots(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres d (Ast0.Ddots(dots,whencode)) ln ln
+ | Ast0.OptDecl(decl) ->
+ let decl = declaration decl in
+ mkres d (Ast0.OptDecl(declaration decl)) decl decl
+ | Ast0.UniqueDecl(decl) ->
+ let decl = declaration decl in
+ mkres d (Ast0.UniqueDecl(declaration decl)) decl decl
+
+(* --------------------------------------------------------------------- *)
+(* Initializer *)
+
+and is_init_dots i =
+ match Ast0.unwrap i with
+ Ast0.Idots(_,_) -> true
+ | _ -> false
+
+and initialiser i =
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) ->
+ let exp = expression exp in
+ mkres i (Ast0.InitExpr(exp)) exp exp
+ | Ast0.InitList(lb,initlist,rb) ->
+ let initlist =
+ dots is_init_dots (Some(promote_mcode lb)) initialiser initlist in
+ mkres i (Ast0.InitList(lb,initlist,rb))
+ (promote_mcode lb) (promote_mcode rb)
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ let name = ident name in
+ let ini = initialiser ini in
+ mkres i (Ast0.InitGccDotName(dot,name,eq,ini)) (promote_mcode dot) ini
+ | Ast0.InitGccName(name,eq,ini) ->
+ let name = ident name in
+ let ini = initialiser ini in
+ mkres i (Ast0.InitGccName(name,eq,ini)) name ini
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ let exp = expression exp in
+ let ini = initialiser ini in
+ mkres i (Ast0.InitGccIndex(lb,exp,rb,eq,ini)) (promote_mcode lb) ini
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ let exp1 = expression exp1 in
+ let exp2 = expression exp2 in
+ let ini = initialiser ini in
+ mkres i (Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini))
+ (promote_mcode lb) ini
+ | Ast0.IComma(cm) as up ->
+ let ln = promote_mcode cm in mkres i up ln ln
+ | Ast0.Idots(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres i (Ast0.Idots(dots,whencode)) ln ln
+ | Ast0.OptIni(ini) ->
+ let ini = initialiser ini in
+ mkres i (Ast0.OptIni(ini)) ini ini
+ | Ast0.UniqueIni(ini) ->
+ let ini = initialiser ini in
+ mkres i (Ast0.UniqueIni(ini)) ini ini
+
+and initialiser_list prev = dots is_init_dots prev initialiser
+
+(* for export *)
+and initialiser_dots x = dots is_init_dots None initialiser x
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and is_param_dots p =
+ match Ast0.unwrap p with
+ Ast0.Pdots(_) | Ast0.Pcircles(_) -> true
+ | _ -> false
+
+and parameterTypeDef p =
+ match Ast0.unwrap p with
+ Ast0.VoidParam(ty) ->
+ let ty = typeC ty in mkres p (Ast0.VoidParam(ty)) ty ty
+ | Ast0.Param(ty,Some id) ->
+ let id = ident id in
+ let ty = typeC ty in mkres p (Ast0.Param(ty,Some id)) ty id
+ | Ast0.Param(ty,None) ->
+ let ty = typeC ty in mkres p (Ast0.Param(ty,None)) ty ty
+ | Ast0.MetaParam(name,_) as up ->
+ let ln = promote_mcode name in mkres p up ln ln
+ | Ast0.MetaParamList(name,_,_) as up ->
+ let ln = promote_mcode name in mkres p up ln ln
+ | Ast0.PComma(cm) ->
+ let cm = bad_mcode cm in
+ let ln = promote_mcode cm in
+ mkres p (Ast0.PComma(cm)) ln ln
+ | Ast0.Pdots(dots) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres p (Ast0.Pdots(dots)) ln ln
+ | Ast0.Pcircles(dots) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres p (Ast0.Pcircles(dots)) ln ln
+ | Ast0.OptParam(param) ->
+ let res = parameterTypeDef param in
+ mkres p (Ast0.OptParam(res)) res res
+ | Ast0.UniqueParam(param) ->
+ let res = parameterTypeDef param in
+ mkres p (Ast0.UniqueParam(res)) res res
+
+and parameter_list prev = dots is_param_dots prev parameterTypeDef
+
+(* for export *)
+let parameter_dots x = dots is_param_dots None parameterTypeDef x
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+let is_stm_dots s =
+ match Ast0.unwrap s with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_) -> true
+ | _ -> false
+
+let rec statement s =
+ let res =
+ match Ast0.unwrap s with
+ Ast0.Decl((_,bef),decl) ->
+ let decl = declaration decl in
+ let left = promote_to_statement_start decl bef in
+ mkres s (Ast0.Decl((Ast0.get_info left,bef),decl)) decl decl
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ let body =
+ dots is_stm_dots (Some(promote_mcode lbrace)) statement body in
+ mkres s (Ast0.Seq(lbrace,body,rbrace))
+ (promote_mcode lbrace) (promote_mcode rbrace)
+ | Ast0.ExprStatement(exp,sem) ->
+ let exp = expression exp in
+ mkres s (Ast0.ExprStatement(exp,sem)) exp (promote_mcode sem)
+ | Ast0.IfThen(iff,lp,exp,rp,branch,(_,aft)) ->
+ let exp = expression exp in
+ let branch = statement branch in
+ let right = promote_to_statement branch aft in
+ mkres s (Ast0.IfThen(iff,lp,exp,rp,branch,(Ast0.get_info right,aft)))
+ (promote_mcode iff) right
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(_,aft)) ->
+ let exp = expression exp in
+ let branch1 = statement branch1 in
+ let branch2 = statement branch2 in
+ let right = promote_to_statement branch2 aft in
+ mkres s
+ (Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,
+ (Ast0.get_info right,aft)))
+ (promote_mcode iff) right
+ | Ast0.While(wh,lp,exp,rp,body,(_,aft)) ->
+ let exp = expression exp in
+ let body = statement body in
+ let right = promote_to_statement body aft in
+ mkres s (Ast0.While(wh,lp,exp,rp,body,(Ast0.get_info right,aft)))
+ (promote_mcode wh) right
+ | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
+ let body = statement body in
+ let exp = expression exp in
+ mkres s (Ast0.Do(d,body,wh,lp,exp,rp,sem))
+ (promote_mcode d) (promote_mcode sem)
+ | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,(_,aft)) ->
+ let exp1 = get_option expression exp1 in
+ let exp2 = get_option expression exp2 in
+ let exp3 = get_option expression exp3 in
+ let body = statement body in
+ let right = promote_to_statement body aft in
+ mkres s (Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,
+ (Ast0.get_info right,aft)))
+ (promote_mcode fr) right
+ | Ast0.Iterator(nm,lp,args,rp,body,(_,aft)) ->
+ let nm = ident nm in
+ let args = dots is_exp_dots (Some(promote_mcode lp)) expression args in
+ let body = statement body in
+ let right = promote_to_statement body aft in
+ mkres s (Ast0.Iterator(nm,lp,args,rp,body,(Ast0.get_info right,aft)))
+ nm right
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ let exp = expression exp in
+ let cases =
+ dots (function _ -> false) (Some(promote_mcode lb)) case_line cases in
+ mkres s
+ (Ast0.Switch(switch,lp,exp,rp,lb,cases,rb))
+ (promote_mcode switch) (promote_mcode rb)
+ | Ast0.Break(br,sem) as us ->
+ mkres s us (promote_mcode br) (promote_mcode sem)
+ | Ast0.Continue(cont,sem) as us ->
+ mkres s us (promote_mcode cont) (promote_mcode sem)
+ | Ast0.Label(l,dd) ->
+ let l = ident l in
+ mkres s (Ast0.Label(l,dd)) l (promote_mcode dd)
+ | Ast0.Goto(goto,id,sem) ->
+ let id = ident id in
+ mkres s (Ast0.Goto(goto,id,sem))
+ (promote_mcode goto) (promote_mcode sem)
+ | Ast0.Return(ret,sem) as us ->
+ mkres s us (promote_mcode ret) (promote_mcode sem)
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ let exp = expression exp in
+ mkres s (Ast0.ReturnExpr(ret,exp,sem))
+ (promote_mcode ret) (promote_mcode sem)
+ | Ast0.MetaStmt(name,_)
+ | Ast0.MetaStmtList(name,_) as us ->
+ let ln = promote_mcode name in mkres s us ln ln
+ | Ast0.Exp(exp) ->
+ let exp = expression exp in
+ mkres s (Ast0.Exp(exp)) exp exp
+ | Ast0.TopExp(exp) ->
+ let exp = expression exp in
+ mkres s (Ast0.TopExp(exp)) exp exp
+ | Ast0.Ty(ty) ->
+ let ty = typeC ty in
+ mkres s (Ast0.Ty(ty)) ty ty
+ | Ast0.Disj(starter,rule_elem_dots_list,mids,ender) ->
+ let starter = bad_mcode starter in
+ let mids = List.map bad_mcode mids in
+ let ender = bad_mcode ender in
+ let rec loop prevs = function
+ [] -> []
+ | stm::stms ->
+ (dots is_stm_dots (Some(promote_mcode_plus_one(List.hd prevs)))
+ statement stm)::
+ (loop (List.tl prevs) stms) in
+ let elems = loop (starter::mids) rule_elem_dots_list in
+ mkmultires s (Ast0.Disj(starter,elems,mids,ender))
+ (promote_mcode starter) (promote_mcode ender)
+ (get_all_start_info elems) (get_all_end_info elems)
+ | Ast0.Nest(starter,rule_elem_dots,ender,whencode,multi) ->
+ let starter = bad_mcode starter in
+ let ender = bad_mcode ender in
+ let rule_elem_dots = dots is_stm_dots None statement rule_elem_dots in
+ mkres s (Ast0.Nest(starter,rule_elem_dots,ender,whencode,multi))
+ (promote_mcode starter) (promote_mcode ender)
+ | Ast0.Dots(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres s (Ast0.Dots(dots,whencode)) ln ln
+ | Ast0.Circles(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres s (Ast0.Circles(dots,whencode)) ln ln
+ | Ast0.Stars(dots,whencode) ->
+ let dots = bad_mcode dots in
+ let ln = promote_mcode dots in
+ mkres s (Ast0.Stars(dots,whencode)) ln ln
+ | Ast0.FunDecl((_,bef),fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ let fninfo =
+ List.map
+ (function Ast0.FType(ty) -> Ast0.FType(typeC ty) | x -> x)
+ fninfo in
+ let name = ident name in
+ let params = parameter_list (Some(promote_mcode lp)) params in
+ let body =
+ dots is_stm_dots (Some(promote_mcode lbrace)) statement body in
+ let left =
+ (* cases on what is leftmost *)
+ match fninfo with
+ [] -> promote_to_statement_start name bef
+ | Ast0.FStorage(stg)::_ ->
+ promote_to_statement_start (promote_mcode stg) bef
+ | Ast0.FType(ty)::_ ->
+ promote_to_statement_start ty bef
+ | Ast0.FInline(inline)::_ ->
+ promote_to_statement_start (promote_mcode inline) bef
+ | Ast0.FAttr(attr)::_ ->
+ promote_to_statement_start (promote_mcode attr) bef in
+ (* pretend it is one line before the start of the function, so that it
+ will catch things defined at top level. We assume that these will not
+ be defined on the same line as the function. This is a HACK.
+ A better approach would be to attach top_level things to this node,
+ and other things to the node after, but that would complicate
+ insert_plus, which doesn't distinguish between different mcodekinds *)
+ let res =
+ Ast0.FunDecl((Ast0.get_info left,bef),fninfo,name,lp,params,rp,lbrace,
+ body,rbrace) in
+ (* have to do this test again, because of typing problems - can't save
+ the result, only use it *)
+ (match fninfo with
+ [] -> mkres s res name (promote_mcode rbrace)
+ | Ast0.FStorage(stg)::_ ->
+ mkres s res (promote_mcode stg) (promote_mcode rbrace)
+ | Ast0.FType(ty)::_ -> mkres s res ty (promote_mcode rbrace)
+ | Ast0.FInline(inline)::_ ->
+ mkres s res (promote_mcode inline) (promote_mcode rbrace)
+ | Ast0.FAttr(attr)::_ ->
+ mkres s res (promote_mcode attr) (promote_mcode rbrace))
+
+ | Ast0.Include(inc,stm) ->
+ mkres s (Ast0.Include(inc,stm)) (promote_mcode inc) (promote_mcode stm)
+ | Ast0.Define(def,id,params,body) ->
+ let id = ident id in
+ let body = dots is_stm_dots None statement body in
+ mkres s (Ast0.Define(def,id,params,body)) (promote_mcode def) body
+ | Ast0.OptStm(stm) ->
+ let stm = statement stm in mkres s (Ast0.OptStm(stm)) stm stm
+ | Ast0.UniqueStm(stm) ->
+ let stm = statement stm in mkres s (Ast0.UniqueStm(stm)) stm stm in
+ Ast0.set_dots_bef_aft res
+ (match Ast0.get_dots_bef_aft res with
+ Ast0.NoDots -> Ast0.NoDots
+ | Ast0.AddingBetweenDots s ->
+ Ast0.AddingBetweenDots(statement s)
+ | Ast0.DroppingBetweenDots s ->
+ Ast0.DroppingBetweenDots(statement s))
+
+and case_line c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ let code = dots is_stm_dots (Some(promote_mcode colon)) statement code in
+ mkres c (Ast0.Default(def,colon,code)) (promote_mcode def) code
+ | Ast0.Case(case,exp,colon,code) ->
+ let exp = expression exp in
+ let code = dots is_stm_dots (Some(promote_mcode colon)) statement code in
+ mkres c (Ast0.Case(case,exp,colon,code)) (promote_mcode case) code
+ | Ast0.OptCase(case) ->
+ let case = case_line case in mkres c (Ast0.OptCase(case)) case case
+
+and statement_dots x = dots is_stm_dots None statement x
+
+(* --------------------------------------------------------------------- *)
+(* Function declaration *)
+
+let top_level t =
+ match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) -> t
+ | Ast0.DECL(stmt) ->
+ let stmt = statement stmt in mkres t (Ast0.DECL(stmt)) stmt stmt
+ | Ast0.CODE(rule_elem_dots) ->
+ let rule_elem_dots = dots is_stm_dots None statement rule_elem_dots in
+ mkres t (Ast0.CODE(rule_elem_dots)) rule_elem_dots rule_elem_dots
+ | Ast0.ERRORWORDS(exps) -> t
+ | Ast0.OTHER(_) -> failwith "eliminated by top_level"
+
+(* --------------------------------------------------------------------- *)
+(* Entry points *)
+
+let compute_lines = List.map top_level
+
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Detects subtrees that are all minus/plus and nodes that are "binding
+context nodes". The latter is a node whose structure and immediate tokens
+are the same in the minus and plus trees, and such that for every child,
+the set of context nodes in the child subtree is the same in the minus and
+plus subtrees. *)
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+module U = Unparse_ast0
+
+(* --------------------------------------------------------------------- *)
+(* Generic access to code *)
+
+let set_mcodekind x mcodekind =
+ match x with
+ Ast0.DotsExprTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsInitTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsParamTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsStmtTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsDeclTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsCaseTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.IdentTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.ExprTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.ParamTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DeclTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.InitTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.StmtTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.CaseLineTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.TopTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+
+let set_index x index =
+ match x with
+ Ast0.DotsExprTag(d) -> Ast0.set_index d index
+ | Ast0.DotsInitTag(d) -> Ast0.set_index d index
+ | Ast0.DotsParamTag(d) -> Ast0.set_index d index
+ | Ast0.DotsStmtTag(d) -> Ast0.set_index d index
+ | Ast0.DotsDeclTag(d) -> Ast0.set_index d index
+ | Ast0.DotsCaseTag(d) -> Ast0.set_index d index
+ | Ast0.IdentTag(d) -> Ast0.set_index d index
+ | Ast0.ExprTag(d) -> Ast0.set_index d index
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Ast0.set_index d index
+ | Ast0.ParamTag(d) -> Ast0.set_index d index
+ | Ast0.InitTag(d) -> Ast0.set_index d index
+ | Ast0.DeclTag(d) -> Ast0.set_index d index
+ | Ast0.StmtTag(d) -> Ast0.set_index d index
+ | Ast0.CaseLineTag(d) -> Ast0.set_index d index
+ | Ast0.TopTag(d) -> Ast0.set_index d index
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+
+let get_index = function
+ Ast0.DotsExprTag(d) -> Index.expression_dots d
+ | Ast0.DotsInitTag(d) -> Index.initialiser_dots d
+ | Ast0.DotsParamTag(d) -> Index.parameter_dots d
+ | Ast0.DotsStmtTag(d) -> Index.statement_dots d
+ | Ast0.DotsDeclTag(d) -> Index.declaration_dots d
+ | Ast0.DotsCaseTag(d) -> Index.case_line_dots d
+ | Ast0.IdentTag(d) -> Index.ident d
+ | Ast0.ExprTag(d) -> Index.expression d
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Index.typeC d
+ | Ast0.ParamTag(d) -> Index.parameterTypeDef d
+ | Ast0.InitTag(d) -> Index.initialiser d
+ | Ast0.DeclTag(d) -> Index.declaration d
+ | Ast0.StmtTag(d) -> Index.statement d
+ | Ast0.CaseLineTag(d) -> Index.case_line d
+ | Ast0.TopTag(d) -> Index.top_level d
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+
+(* --------------------------------------------------------------------- *)
+(* Collect the line numbers of the plus code. This is used for disjunctions.
+It is not completely clear why this is necessary, but it seems like an easy
+fix for whatever is the problem that is discussed in disj_cases *)
+
+let plus_lines = ref ([] : int list)
+
+let insert n =
+ let rec loop = function
+ [] -> [n]
+ | x::xs ->
+ match compare n x with
+ 1 -> x::(loop xs)
+ | 0 -> x::xs
+ | -1 -> n::x::xs
+ | _ -> failwith "not possible" in
+ plus_lines := loop !plus_lines
+
+let find n min max =
+ let rec loop = function
+ [] -> (min,max)
+ | [x] -> if n < x then (min,x) else (x,max)
+ | x1::x2::rest ->
+ if n < x1
+ then (min,x1)
+ else if n > x1 && n < x2 then (x1,x2) else loop (x2::rest) in
+ loop !plus_lines
+
+let collect_plus_lines top =
+ plus_lines := [];
+ let bind x y = () in
+ let option_default = () in
+ let donothing r k e = k e in
+ let mcode (_,_,info,mcodekind,_) =
+ match mcodekind with
+ Ast0.PLUS -> insert info.Ast0.line_start
+ | _ -> () in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing in
+ fn.V0.combiner_top_level top
+
+(* --------------------------------------------------------------------- *)
+
+type kind = Neutral | AllMarked | NotAllMarked (* marked means + or - *)
+
+(* --------------------------------------------------------------------- *)
+(* The first part analyzes each of the minus tree and the plus tree
+separately *)
+
+(* ints are unique token indices (offset field) *)
+type node =
+ Token (* tokens *) of kind * int (* unique index *) * Ast0.mcodekind *
+ int list (* context tokens *)
+ | Recursor (* children *) of kind *
+ int list (* indices of all tokens at the level below *) *
+ Ast0.mcodekind list (* tokens at the level below *) *
+ int list
+ | Bind (* neighbors *) of kind *
+ int list (* indices of all tokens at current level *) *
+ Ast0.mcodekind list (* tokens at current level *) *
+ int list (* indices of all tokens at the level below *) *
+ Ast0.mcodekind list (* tokens at the level below *)
+ * int list list
+
+let kind2c = function
+ Neutral -> "neutral"
+ | AllMarked -> "allmarked"
+ | NotAllMarked -> "notallmarked"
+
+let node2c = function
+ Token(k,_,_,_) -> Printf.sprintf "token %s\n" (kind2c k)
+ | Recursor(k,_,_,_) -> Printf.sprintf "recursor %s\n" (kind2c k)
+ | Bind(k,_,_,_,_,_) -> Printf.sprintf "bind %s\n" (kind2c k)
+
+(* goal: detect negative in both tokens and recursors, or context only in
+tokens *)
+let bind c1 c2 =
+ let lub = function
+ (k1,k2) when k1 = k2 -> k1
+ | (Neutral,AllMarked) -> AllMarked
+ | (AllMarked,Neutral) -> AllMarked
+ | _ -> NotAllMarked in
+ match (c1,c2) with
+ (* token/token *)
+ (* there are tokens at this level, so ignore the level below *)
+ (Token(k1,i1,t1,l1),Token(k2,i2,t2,l2)) ->
+ Bind(lub(k1,k2),[i1;i2],[t1;t2],[],[],[l1;l2])
+
+ (* token/recursor *)
+ (* there are tokens at this level, so ignore the level below *)
+ | (Token(k1,i1,t1,l1),Recursor(k2,_,_,l2)) ->
+ Bind(lub(k1,k2),[i1],[t1],[],[],[l1;l2])
+ | (Recursor(k1,_,_,l1),Token(k2,i2,t2,l2)) ->
+ Bind(lub(k1,k2),[i2],[t2],[],[],[l1;l2])
+
+ (* token/bind *)
+ (* there are tokens at this level, so ignore the level below *)
+ | (Token(k1,i1,t1,l1),Bind(k2,i2,t2,_,_,l2)) ->
+ Bind(lub(k1,k2),i1::i2,t1::t2,[],[],l1::l2)
+ | (Bind(k1,i1,t1,_,_,l1),Token(k2,i2,t2,l2)) ->
+ Bind(lub(k1,k2),i1@[i2],t1@[t2],[],[],l1@[l2])
+
+ (* recursor/bind *)
+ | (Recursor(k1,bi1,bt1,l1),Bind(k2,i2,t2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),i2,t2,bi1@bi2,bt1@bt2,l1::l2)
+ | (Bind(k1,i1,t1,bi1,bt1,l1),Recursor(k2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),i1,t1,bi1@bi2,bt1@bt2,l1@[l2])
+
+ (* recursor/recursor and bind/bind - not likely to ever occur *)
+ | (Recursor(k1,bi1,bt1,l1),Recursor(k2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),[],[],bi1@bi2,bt1@bt2,[l1;l2])
+ | (Bind(k1,i1,t1,bi1,bt1,l1),Bind(k2,i2,t2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),i1@i2,t1@t2,bi1@bi2,bt1@bt2,l1@l2)
+
+
+let option_default = (*Bind(Neutral,[],[],[],[],[])*)
+ Recursor(Neutral,[],[],[])
+
+let mcode (_,_,info,mcodekind,pos) =
+ let offset = info.Ast0.offset in
+ match mcodekind with
+ Ast0.MINUS(_) -> Token(AllMarked,offset,mcodekind,[])
+ | Ast0.PLUS -> Token(AllMarked,offset,mcodekind,[])
+ | Ast0.CONTEXT(_) -> Token(NotAllMarked,offset,mcodekind,[offset])
+ | _ -> failwith "not possible"
+
+let neutral_mcode (_,_,info,mcodekind,pos) =
+ let offset = info.Ast0.offset in
+ match mcodekind with
+ Ast0.MINUS(_) -> Token(Neutral,offset,mcodekind,[])
+ | Ast0.PLUS -> Token(Neutral,offset,mcodekind,[])
+ | Ast0.CONTEXT(_) -> Token(Neutral,offset,mcodekind,[offset])
+ | _ -> failwith "not possible"
+
+let is_context = function Ast0.CONTEXT(_) -> true | _ -> false
+
+let union_all l = List.fold_left Common.union_set [] l
+
+(* is minus is true when we are processing minus code that might be
+intermingled with plus code. it is used in disj_cases *)
+let classify is_minus all_marked table code =
+ let mkres builder k il tl bil btl l e =
+ (if k = AllMarked
+ then Ast0.set_mcodekind e (all_marked()) (* definitive *)
+ else
+ let check_index il tl =
+ if List.for_all is_context tl
+ then
+ (let e1 = builder e in
+ let index = (get_index e1)@il in
+ try
+ let _ = Hashtbl.find table index in
+ failwith
+ (Printf.sprintf "%d: index %s already used\n"
+ (Ast0.get_info e).Ast0.line_start
+ (String.concat " " (List.map string_of_int index)))
+ with Not_found -> Hashtbl.add table index (e1,l)) in
+ if il = [] then check_index bil btl else check_index il tl);
+ if il = []
+ then Recursor(k, bil, btl, union_all l)
+ else Recursor(k, il, tl, union_all l) in
+
+ let compute_result builder e = function
+ Bind(k,il,tl,bil,btl,l) -> mkres builder k il tl bil btl l e
+ | Token(k,il,tl,l) -> mkres builder k [il] [tl] [] [] [l] e
+ | Recursor(k,bil,btl,l) -> mkres builder k [] [] bil btl [l] e in
+
+ let make_not_marked = function
+ Bind(k,il,tl,bil,btl,l) -> Bind(NotAllMarked,il,tl,bil,btl,l)
+ | Token(k,il,tl,l) -> Token(NotAllMarked,il,tl,l)
+ | Recursor(k,bil,btl,l) -> Recursor(NotAllMarked,bil,btl,l) in
+
+ let do_nothing builder r k e = compute_result builder e (k e) in
+
+ let disj_cases disj starter code fn ender =
+ (* neutral_mcode used so starter and ender don't have an affect on
+ whether the code is considered all plus/minus, but so that they are
+ consider in the index list, which is needed to make a disj with
+ something in one branch and nothing in the other different from code
+ that just has the something (starter/ender enough, mids not needed
+ for this). Cannot agglomerate + code over | boundaries, because two -
+ cases might have different + code, and don't want to put the + code
+ together into one unit. *)
+ let make_not_marked =
+ if is_minus
+ then
+ (let min = Ast0.get_line disj in
+ let max = Ast0.get_line_end disj in
+ let (plus_min,plus_max) = find min (min-1) (max+1) in
+ if max > plus_max then make_not_marked else (function x -> x))
+ else make_not_marked in
+ bind (neutral_mcode starter)
+ (bind (List.fold_right bind
+ (List.map make_not_marked (List.map fn code))
+ option_default)
+ (neutral_mcode ender)) in
+
+ (* no whencode in plus tree so have to drop it *)
+ (* need special cases for dots, nests, and disjs *)
+ let expression r k e =
+ compute_result Ast0.expr e
+ (match Ast0.unwrap e with
+ Ast0.NestExpr(starter,exp,ender,whencode,multi) ->
+ k (Ast0.rewrap e (Ast0.NestExpr(starter,exp,ender,None,multi)))
+ | Ast0.Edots(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Edots(dots,None)))
+ | Ast0.Ecircles(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Ecircles(dots,None)))
+ | Ast0.Estars(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Estars(dots,None)))
+ | Ast0.DisjExpr(starter,expr_list,_,ender) ->
+ disj_cases e starter expr_list r.V0.combiner_expression ender
+ | _ -> k e) in
+
+ (* not clear why we have the next two cases, since DisjDecl and
+ DisjType shouldn't have been constructed yet, as they only come from isos *)
+ let declaration r k e =
+ compute_result Ast0.decl e
+ (match Ast0.unwrap e with
+ Ast0.DisjDecl(starter,decls,_,ender) ->
+ disj_cases e starter decls r.V0.combiner_declaration ender
+ | Ast0.Ddots(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Ddots(dots,None)))
+ (* Need special cases for the following so that the type will be
+ considered as a unit, rather than distributed around the
+ declared variable. This needs to be done because of the call to
+ compute_result, ie the processing of each term should make a
+ side-effect on the complete term structure as well as collecting
+ some information about it. So we have to visit each complete
+ term structure. In (all?) other such cases, we visit the terms
+ using rebuilder, which just visits the subterms, rather than
+ reordering their components. *)
+ | Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ bind (match stg with Some stg -> mcode stg | _ -> option_default)
+ (bind (r.V0.combiner_typeC ty)
+ (bind (r.V0.combiner_ident id)
+ (bind (mcode eq)
+ (bind (r.V0.combiner_initialiser ini) (mcode sem)))))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ bind (match stg with Some stg -> mcode stg | _ -> option_default)
+ (bind (r.V0.combiner_typeC ty)
+ (bind (r.V0.combiner_ident id) (mcode sem)))
+ | _ -> k e) in
+
+ let param r k e =
+ compute_result Ast0.param e
+ (match Ast0.unwrap e with
+ Ast0.Param(ty,Some id) ->
+ (* needed for the same reason as in the Init and UnInit cases *)
+ bind (r.V0.combiner_typeC ty) (r.V0.combiner_ident id)
+ | _ -> k e) in
+
+ let typeC r k e =
+ compute_result Ast0.typeC e
+ (match Ast0.unwrap e with
+ Ast0.DisjType(starter,types,_,ender) ->
+ disj_cases e starter types r.V0.combiner_typeC ender
+ | _ -> k e) in
+
+ let initialiser r k i =
+ compute_result Ast0.ini i
+ (match Ast0.unwrap i with
+ Ast0.Idots(dots,whencode) ->
+ k (Ast0.rewrap i (Ast0.Idots(dots,None)))
+ | _ -> k i) in
+
+ let statement r k s =
+ compute_result Ast0.stmt s
+ (match Ast0.unwrap s with
+ Ast0.Nest(started,stm_dots,ender,whencode,multi) ->
+ k (Ast0.rewrap s (Ast0.Nest(started,stm_dots,ender,[],multi)))
+ | Ast0.Dots(dots,whencode) ->
+ k (Ast0.rewrap s (Ast0.Dots(dots,[])))
+ | Ast0.Circles(dots,whencode) ->
+ k (Ast0.rewrap s (Ast0.Circles(dots,[])))
+ | Ast0.Stars(dots,whencode) ->
+ k (Ast0.rewrap s (Ast0.Stars(dots,[])))
+ | Ast0.Disj(starter,statement_dots_list,_,ender) ->
+ disj_cases s starter statement_dots_list r.V0.combiner_statement_dots
+ ender
+(* Why? There is nothing there
+ (* cases for everything with extra mcode *)
+ | Ast0.FunDecl((info,bef),_,_,_,_,_,_,_,_)
+ | Ast0.Decl((info,bef),_) ->
+ bind (mcode ((),(),info,bef)) (k s)
+ | Ast0.IfThen(_,_,_,_,_,(info,aft))
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft))
+ | Ast0.While(_,_,_,_,_,(info,aft)) ->
+ | Ast0.For(_,_,_,_,_,_,_,_,_,(info,aft)) ->
+ bind (k s) (mcode ((),(),info,aft))
+ | Ast0.Iterator(_,_,_,_,_,(info,aft))
+*)
+ | _ -> k s
+
+) in
+
+ let do_top builder r k e = compute_result builder e (k e) in
+
+ let combiner =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ (do_nothing Ast0.dotsExpr) (do_nothing Ast0.dotsInit)
+ (do_nothing Ast0.dotsParam) (do_nothing Ast0.dotsStmt)
+ (do_nothing Ast0.dotsDecl) (do_nothing Ast0.dotsCase)
+ (do_nothing Ast0.ident) expression typeC initialiser param declaration
+ statement (do_nothing Ast0.case_line) (do_top Ast0.top) in
+ combiner.V0.combiner_top_level code
+
+(* --------------------------------------------------------------------- *)
+(* Traverse the hash tables and find corresponding context nodes that have
+the same context children *)
+
+(* this is just a sanity check - really only need to look at the top-level
+ structure *)
+let equal_mcode (_,_,info1,_,_) (_,_,info2,_,_) =
+ info1.Ast0.offset = info2.Ast0.offset
+
+let equal_option e1 e2 =
+ match (e1,e2) with
+ (Some x, Some y) -> equal_mcode x y
+ | (None, None) -> true
+ | _ -> false
+
+let dots fn d1 d2 =
+ match (Ast0.unwrap d1,Ast0.unwrap d2) with
+ (Ast0.DOTS(l1),Ast0.DOTS(l2)) -> List.length l1 = List.length l2
+ | (Ast0.CIRCLES(l1),Ast0.CIRCLES(l2)) -> List.length l1 = List.length l2
+ | (Ast0.STARS(l1),Ast0.STARS(l2)) -> List.length l1 = List.length l2
+ | _ -> false
+
+let rec equal_ident i1 i2 =
+ match (Ast0.unwrap i1,Ast0.unwrap i2) with
+ (Ast0.Id(name1),Ast0.Id(name2)) -> equal_mcode name1 name2
+ | (Ast0.MetaId(name1,_,_),Ast0.MetaId(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.MetaFunc(name1,_,_),Ast0.MetaFunc(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.MetaLocalFunc(name1,_,_),Ast0.MetaLocalFunc(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.OptIdent(_),Ast0.OptIdent(_)) -> true
+ | (Ast0.UniqueIdent(_),Ast0.UniqueIdent(_)) -> true
+ | _ -> false
+
+let rec equal_expression e1 e2 =
+ match (Ast0.unwrap e1,Ast0.unwrap e2) with
+ (Ast0.Ident(_),Ast0.Ident(_)) -> true
+ | (Ast0.Constant(const1),Ast0.Constant(const2)) -> equal_mcode const1 const2
+ | (Ast0.FunCall(_,lp1,_,rp1),Ast0.FunCall(_,lp2,_,rp2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.Assignment(_,op1,_,_),Ast0.Assignment(_,op2,_,_)) ->
+ equal_mcode op1 op2
+ | (Ast0.CondExpr(_,why1,_,colon1,_),Ast0.CondExpr(_,why2,_,colon2,_)) ->
+ equal_mcode why1 why2 && equal_mcode colon1 colon2
+ | (Ast0.Postfix(_,op1),Ast0.Postfix(_,op2)) -> equal_mcode op1 op2
+ | (Ast0.Infix(_,op1),Ast0.Infix(_,op2)) -> equal_mcode op1 op2
+ | (Ast0.Unary(_,op1),Ast0.Unary(_,op2)) -> equal_mcode op1 op2
+ | (Ast0.Binary(_,op1,_),Ast0.Binary(_,op2,_)) -> equal_mcode op1 op2
+ | (Ast0.Paren(lp1,_,rp1),Ast0.Paren(lp2,_,rp2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.ArrayAccess(_,lb1,_,rb1),Ast0.ArrayAccess(_,lb2,_,rb2)) ->
+ equal_mcode lb1 lb2 && equal_mcode rb1 rb2
+ | (Ast0.RecordAccess(_,pt1,_),Ast0.RecordAccess(_,pt2,_)) ->
+ equal_mcode pt1 pt2
+ | (Ast0.RecordPtAccess(_,ar1,_),Ast0.RecordPtAccess(_,ar2,_)) ->
+ equal_mcode ar1 ar2
+ | (Ast0.Cast(lp1,_,rp1,_),Ast0.Cast(lp2,_,rp2,_)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.SizeOfExpr(szf1,_),Ast0.SizeOfExpr(szf2,_)) ->
+ equal_mcode szf1 szf2
+ | (Ast0.SizeOfType(szf1,lp1,_,rp1),Ast0.SizeOfType(szf2,lp2,_,rp2)) ->
+ equal_mcode szf1 szf2 && equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.TypeExp(_),Ast0.TypeExp(_)) -> true
+ | (Ast0.MetaErr(name1,_,_),Ast0.MetaErr(name2,_,_))
+ | (Ast0.MetaExpr(name1,_,_,_,_),Ast0.MetaExpr(name2,_,_,_,_))
+ | (Ast0.MetaExprList(name1,_,_),Ast0.MetaExprList(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.EComma(cm1),Ast0.EComma(cm2)) -> equal_mcode cm1 cm2
+ | (Ast0.DisjExpr(starter1,_,mids1,ender1),
+ Ast0.DisjExpr(starter2,_,mids2,ender2)) ->
+ equal_mcode starter1 starter2 &&
+ List.for_all2 equal_mcode mids1 mids2 &&
+ equal_mcode ender1 ender2
+ | (Ast0.NestExpr(starter1,_,ender1,_,m1),
+ Ast0.NestExpr(starter2,_,ender2,_,m2)) ->
+ equal_mcode starter1 starter2 && equal_mcode ender1 ender2 && m1 = m2
+ | (Ast0.Edots(dots1,_),Ast0.Edots(dots2,_))
+ | (Ast0.Ecircles(dots1,_),Ast0.Ecircles(dots2,_))
+ | (Ast0.Estars(dots1,_),Ast0.Estars(dots2,_)) -> equal_mcode dots1 dots2
+ | (Ast0.OptExp(_),Ast0.OptExp(_)) -> true
+ | (Ast0.UniqueExp(_),Ast0.UniqueExp(_)) -> true
+ | _ -> false
+
+let rec equal_typeC t1 t2 =
+ match (Ast0.unwrap t1,Ast0.unwrap t2) with
+ (Ast0.ConstVol(cv1,_),Ast0.ConstVol(cv2,_)) -> equal_mcode cv1 cv2
+ | (Ast0.BaseType(ty1,sign1),Ast0.BaseType(ty2,sign2)) ->
+ equal_mcode ty1 ty2 && equal_option sign1 sign2
+ | (Ast0.ImplicitInt(sign1),Ast0.ImplicitInt(sign2)) ->
+ equal_mcode sign1 sign2
+ | (Ast0.Pointer(_,star1),Ast0.Pointer(_,star2)) ->
+ equal_mcode star1 star2
+ | (Ast0.Array(_,lb1,_,rb1),Ast0.Array(_,lb2,_,rb2)) ->
+ equal_mcode lb1 lb2 && equal_mcode rb1 rb2
+ | (Ast0.StructUnionName(kind1,_),Ast0.StructUnionName(kind2,_)) ->
+ equal_mcode kind1 kind2
+ | (Ast0.FunctionType(ty1,lp1,p1,rp1),Ast0.FunctionType(ty2,lp2,p2,rp2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.StructUnionDef(_,lb1,_,rb1),
+ Ast0.StructUnionDef(_,lb2,_,rb2)) ->
+ equal_mcode lb1 lb2 && equal_mcode rb1 rb2
+ | (Ast0.TypeName(name1),Ast0.TypeName(name2)) -> equal_mcode name1 name2
+ | (Ast0.MetaType(name1,_),Ast0.MetaType(name2,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.DisjType(starter1,_,mids1,ender1),
+ Ast0.DisjType(starter2,_,mids2,ender2)) ->
+ equal_mcode starter1 starter2 &&
+ List.for_all2 equal_mcode mids1 mids2 &&
+ equal_mcode ender1 ender2
+ | (Ast0.OptType(_),Ast0.OptType(_)) -> true
+ | (Ast0.UniqueType(_),Ast0.UniqueType(_)) -> true
+ | _ -> false
+
+let equal_declaration d1 d2 =
+ match (Ast0.unwrap d1,Ast0.unwrap d2) with
+ (Ast0.Init(stg1,_,_,eq1,_,sem1),Ast0.Init(stg2,_,_,eq2,_,sem2)) ->
+ equal_option stg1 stg2 && equal_mcode eq1 eq2 && equal_mcode sem1 sem2
+ | (Ast0.UnInit(stg1,_,_,sem1),Ast0.UnInit(stg2,_,_,sem2)) ->
+ equal_option stg1 stg2 && equal_mcode sem1 sem2
+ | (Ast0.MacroDecl(nm1,lp1,_,rp1,sem1),Ast0.MacroDecl(nm2,lp2,_,rp2,sem2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode sem1 sem2
+ | (Ast0.TyDecl(_,sem1),Ast0.TyDecl(_,sem2)) -> equal_mcode sem1 sem2
+ | (Ast0.Ddots(dots1,_),Ast0.Ddots(dots2,_)) -> equal_mcode dots1 dots2
+ | (Ast0.OptDecl(_),Ast0.OptDecl(_)) -> true
+ | (Ast0.UniqueDecl(_),Ast0.UniqueDecl(_)) -> true
+ | (Ast0.DisjDecl _,_) | (_,Ast0.DisjDecl _) ->
+ failwith "DisjDecl not expected here"
+ | _ -> false
+
+let equal_initialiser i1 i2 =
+ match (Ast0.unwrap i1,Ast0.unwrap i2) with
+ (Ast0.InitExpr(_),Ast0.InitExpr(_)) -> true
+ | (Ast0.InitList(lb1,_,rb1),Ast0.InitList(lb2,_,rb2)) ->
+ (equal_mcode lb1 lb2) && (equal_mcode rb1 rb2)
+ | (Ast0.InitGccDotName(dot1,_,eq1,_),Ast0.InitGccDotName(dot2,_,eq2,_)) ->
+ (equal_mcode dot1 dot2) && (equal_mcode eq1 eq2)
+ | (Ast0.InitGccName(_,eq1,_),Ast0.InitGccName(_,eq2,_)) ->
+ equal_mcode eq1 eq2
+ | (Ast0.InitGccIndex(lb1,_,rb1,eq1,_),Ast0.InitGccIndex(lb2,_,rb2,eq2,_)) ->
+ (equal_mcode lb1 lb2) && (equal_mcode rb1 rb2) && (equal_mcode eq1 eq2)
+ | (Ast0.InitGccRange(lb1,_,dots1,_,rb1,eq1,_),
+ Ast0.InitGccRange(lb2,_,dots2,_,rb2,eq2,_)) ->
+ (equal_mcode lb1 lb2) && (equal_mcode dots1 dots2) &&
+ (equal_mcode rb1 rb2) && (equal_mcode eq1 eq2)
+ | (Ast0.IComma(cm1),Ast0.IComma(cm2)) -> equal_mcode cm1 cm2
+ | (Ast0.Idots(d1,_),Ast0.Idots(d2,_)) -> equal_mcode d1 d2
+ | (Ast0.OptIni(_),Ast0.OptIni(_)) -> true
+ | (Ast0.UniqueIni(_),Ast0.UniqueIni(_)) -> true
+ | _ -> false
+
+let equal_parameterTypeDef p1 p2 =
+ match (Ast0.unwrap p1,Ast0.unwrap p2) with
+ (Ast0.VoidParam(_),Ast0.VoidParam(_)) -> true
+ | (Ast0.Param(_,_),Ast0.Param(_,_)) -> true
+ | (Ast0.MetaParam(name1,_),Ast0.MetaParam(name2,_))
+ | (Ast0.MetaParamList(name1,_,_),Ast0.MetaParamList(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.PComma(cm1),Ast0.PComma(cm2)) -> equal_mcode cm1 cm2
+ | (Ast0.Pdots(dots1),Ast0.Pdots(dots2))
+ | (Ast0.Pcircles(dots1),Ast0.Pcircles(dots2)) -> equal_mcode dots1 dots2
+ | (Ast0.OptParam(_),Ast0.OptParam(_)) -> true
+ | (Ast0.UniqueParam(_),Ast0.UniqueParam(_)) -> true
+ | _ -> false
+
+let rec equal_statement s1 s2 =
+ match (Ast0.unwrap s1,Ast0.unwrap s2) with
+ (Ast0.FunDecl(_,fninfo1,_,lp1,_,rp1,lbrace1,_,rbrace1),
+ Ast0.FunDecl(_,fninfo2,_,lp2,_,rp2,lbrace2,_,rbrace2)) ->
+ (List.length fninfo1) = (List.length fninfo2) &&
+ List.for_all2 equal_fninfo fninfo1 fninfo2 &&
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 &&
+ equal_mcode lbrace1 lbrace2 && equal_mcode rbrace1 rbrace2
+ | (Ast0.Decl(_,_),Ast0.Decl(_,_)) -> true
+ | (Ast0.Seq(lbrace1,_,rbrace1),Ast0.Seq(lbrace2,_,rbrace2)) ->
+ equal_mcode lbrace1 lbrace2 && equal_mcode rbrace1 rbrace2
+ | (Ast0.ExprStatement(_,sem1),Ast0.ExprStatement(_,sem2)) ->
+ equal_mcode sem1 sem2
+ | (Ast0.IfThen(iff1,lp1,_,rp1,_,_),Ast0.IfThen(iff2,lp2,_,rp2,_,_)) ->
+ equal_mcode iff1 iff2 && equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.IfThenElse(iff1,lp1,_,rp1,_,els1,_,_),
+ Ast0.IfThenElse(iff2,lp2,_,rp2,_,els2,_,_)) ->
+ equal_mcode iff1 iff2 &&
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode els1 els2
+ | (Ast0.While(whl1,lp1,_,rp1,_,_),Ast0.While(whl2,lp2,_,rp2,_,_)) ->
+ equal_mcode whl1 whl2 && equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.Do(d1,_,whl1,lp1,_,rp1,sem1),Ast0.Do(d2,_,whl2,lp2,_,rp2,sem2)) ->
+ equal_mcode whl1 whl2 && equal_mcode d1 d2 &&
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode sem1 sem2
+ | (Ast0.For(fr1,lp1,_,sem11,_,sem21,_,rp1,_,_),
+ Ast0.For(fr2,lp2,_,sem12,_,sem22,_,rp2,_,_)) ->
+ equal_mcode fr1 fr2 && equal_mcode lp1 lp2 &&
+ equal_mcode sem11 sem12 && equal_mcode sem21 sem22 &&
+ equal_mcode rp1 rp2
+ | (Ast0.Iterator(nm1,lp1,_,rp1,_,_),Ast0.Iterator(nm2,lp2,_,rp2,_,_)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.Switch(switch1,lp1,_,rp1,lb1,case1,rb1),
+ Ast0.Switch(switch2,lp2,_,rp2,lb2,case2,rb2)) ->
+ equal_mcode switch1 switch2 && equal_mcode lp1 lp2 &&
+ equal_mcode rp1 rp2 && equal_mcode lb1 lb2 &&
+ equal_mcode rb1 rb2
+ | (Ast0.Break(br1,sem1),Ast0.Break(br2,sem2)) ->
+ equal_mcode br1 br2 && equal_mcode sem1 sem2
+ | (Ast0.Continue(cont1,sem1),Ast0.Continue(cont2,sem2)) ->
+ equal_mcode cont1 cont2 && equal_mcode sem1 sem2
+ | (Ast0.Label(_,dd1),Ast0.Label(_,dd2)) ->
+ equal_mcode dd1 dd2
+ | (Ast0.Goto(g1,_,sem1),Ast0.Goto(g2,_,sem2)) ->
+ equal_mcode g1 g2 && equal_mcode sem1 sem2
+ | (Ast0.Return(ret1,sem1),Ast0.Return(ret2,sem2)) ->
+ equal_mcode ret1 ret2 && equal_mcode sem1 sem2
+ | (Ast0.ReturnExpr(ret1,_,sem1),Ast0.ReturnExpr(ret2,_,sem2)) ->
+ equal_mcode ret1 ret2 && equal_mcode sem1 sem2
+ | (Ast0.MetaStmt(name1,_),Ast0.MetaStmt(name2,_))
+ | (Ast0.MetaStmtList(name1,_),Ast0.MetaStmtList(name2,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.Disj(starter1,_,mids1,ender1),Ast0.Disj(starter2,_,mids2,ender2)) ->
+ equal_mcode starter1 starter2 &&
+ List.for_all2 equal_mcode mids1 mids2 &&
+ equal_mcode ender1 ender2
+ | (Ast0.Nest(starter1,_,ender1,_,m1),Ast0.Nest(starter2,_,ender2,_,m2)) ->
+ equal_mcode starter1 starter2 && equal_mcode ender1 ender2 && m1 = m2
+ | (Ast0.Exp(_),Ast0.Exp(_)) -> true
+ | (Ast0.TopExp(_),Ast0.TopExp(_)) -> true
+ | (Ast0.Ty(_),Ast0.Ty(_)) -> true
+ | (Ast0.Dots(d1,_),Ast0.Dots(d2,_))
+ | (Ast0.Circles(d1,_),Ast0.Circles(d2,_))
+ | (Ast0.Stars(d1,_),Ast0.Stars(d2,_)) -> equal_mcode d1 d2
+ | (Ast0.Include(inc1,name1),Ast0.Include(inc2,name2)) ->
+ equal_mcode inc1 inc2 && equal_mcode name1 name2
+ | (Ast0.Define(def1,_,_,_),Ast0.Define(def2,_,_,_)) ->
+ equal_mcode def1 def2
+ | (Ast0.OptStm(_),Ast0.OptStm(_)) -> true
+ | (Ast0.UniqueStm(_),Ast0.UniqueStm(_)) -> true
+ | _ -> false
+
+and equal_fninfo x y =
+ match (x,y) with
+ (Ast0.FStorage(s1),Ast0.FStorage(s2)) -> equal_mcode s1 s2
+ | (Ast0.FType(_),Ast0.FType(_)) -> true
+ | (Ast0.FInline(i1),Ast0.FInline(i2)) -> equal_mcode i1 i2
+ | (Ast0.FAttr(i1),Ast0.FAttr(i2)) -> equal_mcode i1 i2
+ | _ -> false
+
+let equal_case_line c1 c2 =
+ match (Ast0.unwrap c1,Ast0.unwrap c2) with
+ (Ast0.Default(def1,colon1,_),Ast0.Default(def2,colon2,_)) ->
+ equal_mcode def1 def2 && equal_mcode colon1 colon2
+ | (Ast0.Case(case1,_,colon1,_),Ast0.Case(case2,_,colon2,_)) ->
+ equal_mcode case1 case2 && equal_mcode colon1 colon2
+ | (Ast0.OptCase(_),Ast0.OptCase(_)) -> true
+ | _ -> false
+
+let rec equal_top_level t1 t2 =
+ match (Ast0.unwrap t1,Ast0.unwrap t2) with
+ (Ast0.DECL(_),Ast0.DECL(_)) -> true
+ | (Ast0.FILEINFO(old_file1,new_file1),Ast0.FILEINFO(old_file2,new_file2)) ->
+ equal_mcode old_file1 old_file2 && equal_mcode new_file1 new_file2
+ | (Ast0.CODE(_),Ast0.CODE(_)) -> true
+ | (Ast0.ERRORWORDS(_),Ast0.ERRORWORDS(_)) -> true
+ | _ -> false
+
+let root_equal e1 e2 =
+ match (e1,e2) with
+ (Ast0.DotsExprTag(d1),Ast0.DotsExprTag(d2)) -> dots equal_expression d1 d2
+ | (Ast0.DotsParamTag(d1),Ast0.DotsParamTag(d2)) ->
+ dots equal_parameterTypeDef d1 d2
+ | (Ast0.DotsStmtTag(d1),Ast0.DotsStmtTag(d2)) -> dots equal_statement d1 d2
+ | (Ast0.DotsDeclTag(d1),Ast0.DotsDeclTag(d2)) -> dots equal_declaration d1 d2
+ | (Ast0.DotsCaseTag(d1),Ast0.DotsCaseTag(d2)) -> dots equal_case_line d1 d2
+ | (Ast0.IdentTag(i1),Ast0.IdentTag(i2)) -> equal_ident i1 i2
+ | (Ast0.ExprTag(e1),Ast0.ExprTag(e2)) -> equal_expression e1 e2
+ | (Ast0.ArgExprTag(d),_) -> failwith "not possible - iso only"
+ | (Ast0.TypeCTag(t1),Ast0.TypeCTag(t2)) -> equal_typeC t1 t2
+ | (Ast0.ParamTag(p1),Ast0.ParamTag(p2)) -> equal_parameterTypeDef p1 p2
+ | (Ast0.InitTag(d1),Ast0.InitTag(d2)) -> equal_initialiser d1 d2
+ | (Ast0.DeclTag(d1),Ast0.DeclTag(d2)) -> equal_declaration d1 d2
+ | (Ast0.StmtTag(s1),Ast0.StmtTag(s2)) -> equal_statement s1 s2
+ | (Ast0.TopTag(t1),Ast0.TopTag(t2)) -> equal_top_level t1 t2
+ | (Ast0.IsoWhenTag(_),_) | (_,Ast0.IsoWhenTag(_)) ->
+ failwith "only within iso phase"
+ | _ -> false
+
+let default_context _ =
+ Ast0.CONTEXT(ref(Ast.NOTHING,
+ Ast0.default_token_info,Ast0.default_token_info))
+
+let traverse minus_table plus_table =
+ Hashtbl.iter
+ (function key ->
+ function (e,l) ->
+ try
+ let (plus_e,plus_l) = Hashtbl.find plus_table key in
+ if root_equal e plus_e &&
+ List.for_all (function x -> x)
+ (List.map2 Common.equal_set l plus_l)
+ then
+ let i = Ast0.fresh_index() in
+ (set_index e i; set_index plus_e i;
+ set_mcodekind e (default_context());
+ set_mcodekind plus_e (default_context()))
+ with Not_found -> ())
+ minus_table
+
+(* --------------------------------------------------------------------- *)
+(* contextify the whencode *)
+
+let contextify_all =
+ let bind x y = () in
+ let option_default = () in
+ let mcode x = () in
+ let do_nothing r k e = Ast0.set_mcodekind e (default_context()); k e in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing
+
+let contextify_whencode =
+ let bind x y = () in
+ let option_default = () in
+ let mcode x = () in
+ let do_nothing r k e = k e in
+
+ let expression r k e =
+ k e;
+ match Ast0.unwrap e with
+ Ast0.NestExpr(_,_,_,Some whencode,_)
+ | Ast0.Edots(_,Some whencode)
+ | Ast0.Ecircles(_,Some whencode)
+ | Ast0.Estars(_,Some whencode) ->
+ contextify_all.V0.combiner_expression whencode
+ | _ -> () in
+
+ let initialiser r k i =
+ match Ast0.unwrap i with
+ Ast0.Idots(dots,Some whencode) ->
+ contextify_all.V0.combiner_initialiser whencode
+ | _ -> k i in
+
+ let whencode = function
+ Ast0.WhenNot sd -> contextify_all.V0.combiner_statement_dots sd
+ | Ast0.WhenAlways s -> contextify_all.V0.combiner_statement s
+ | Ast0.WhenModifier(_) -> () in
+
+ let statement r k (s : Ast0.statement) =
+ k s;
+ match Ast0.unwrap s with
+ Ast0.Nest(_,_,_,whn,_)
+ | Ast0.Dots(_,whn) | Ast0.Circles(_,whn) | Ast0.Stars(_,whn) ->
+ List.iter whencode whn
+ | _ -> () in
+
+ let combiner =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing
+ expression
+ do_nothing initialiser do_nothing do_nothing statement do_nothing
+ do_nothing in
+ combiner.V0.combiner_top_level
+
+(* --------------------------------------------------------------------- *)
+
+(* the first int list is the tokens in the node, the second is the tokens
+in the descendents *)
+let minus_table =
+ (Hashtbl.create(50) : (int list, Ast0.anything * int list list) Hashtbl.t)
+let plus_table =
+ (Hashtbl.create(50) : (int list, Ast0.anything * int list list) Hashtbl.t)
+
+let iscode t =
+ match Ast0.unwrap t with
+ Ast0.DECL(_) -> true
+ | Ast0.FILEINFO(_) -> true
+ | Ast0.ERRORWORDS(_) -> false
+ | Ast0.CODE(_) -> true
+ | Ast0.OTHER(_) -> failwith "unexpected top level code"
+
+(* ------------------------------------------------------------------- *)
+(* alignment of minus and plus *)
+
+let concat = function
+ [] -> []
+ | [s] -> [s]
+ | l ->
+ let rec loop = function
+ [] -> []
+ | x::rest ->
+ (match Ast0.unwrap x with
+ Ast0.DECL(s) -> let stms = loop rest in s::stms
+ | Ast0.CODE(ss) ->
+ let stms = loop rest in
+ (match Ast0.unwrap ss with
+ Ast0.DOTS(d) -> d@stms
+ | _ -> failwith "no dots allowed in pure plus code")
+ | _ -> failwith "plus code is being discarded") in
+ let res =
+ Compute_lines.statement_dots
+ (Ast0.rewrap (List.hd l) (Ast0.DOTS (loop l))) in
+ [Ast0.rewrap res (Ast0.CODE res)]
+
+let collect_up_to m plus =
+ let minfo = Ast0.get_info m in
+ let mend = minfo.Ast0.logical_end in
+ let rec loop = function
+ [] -> ([],[])
+ | p::plus ->
+ let pinfo = Ast0.get_info p in
+ let pstart = pinfo.Ast0.logical_start in
+ if pstart > mend
+ then ([],p::plus)
+ else let (plus,rest) = loop plus in (p::plus,rest) in
+ let (plus,rest) = loop plus in
+ (concat plus,rest)
+
+let realign minus plus =
+ let rec loop = function
+ ([],_) -> failwith "not possible, some context required"
+ | ([m],p) -> ([m],concat p)
+ | (m::minus,plus) ->
+ let (p,plus) = collect_up_to m plus in
+ let (minus,plus) = loop (minus,plus) in
+ (m::minus,p@plus) in
+ loop (minus,plus)
+
+(* ------------------------------------------------------------------- *)
+(* check compatible: check that at the top level the minus and plus code is
+of the same kind. Could go further and make the correspondence between the
+code between ...s. *)
+
+let isonly f l = match Ast0.undots l with [s] -> f s | _ -> false
+
+let isall f l = List.for_all (isonly f) l
+
+let rec is_exp s =
+ match Ast0.unwrap s with
+ Ast0.Exp(e) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_exp stmts
+ | _ -> false
+
+let rec is_ty s =
+ match Ast0.unwrap s with
+ Ast0.Ty(e) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_ty stmts
+ | _ -> false
+
+let rec is_decl s =
+ match Ast0.unwrap s with
+ Ast0.Decl(_,e) -> true
+ | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_decl stmts
+ | _ -> false
+
+let rec is_fndecl s =
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_fndecl stmts
+ | _ -> false
+
+let rec is_toplevel s =
+ match Ast0.unwrap s with
+ Ast0.Decl(_,e) -> true
+ | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_toplevel stmts
+ | Ast0.ExprStatement(fc,_) ->
+ (match Ast0.unwrap fc with
+ Ast0.FunCall(_,_,_,_) -> true
+ | _ -> false)
+ | Ast0.Include(_,_) -> true
+ | Ast0.Define(_,_,_,_) -> true
+ | _ -> false
+
+let check_compatible m p =
+ let fail _ =
+ failwith
+ (Printf.sprintf
+ "incompatible minus and plus code starting on lines %d and %d"
+ (Ast0.get_line m) (Ast0.get_line p)) in
+ match (Ast0.unwrap m, Ast0.unwrap p) with
+ (Ast0.DECL(decl1),Ast0.DECL(decl2)) ->
+ if not (is_decl decl1 && is_decl decl2)
+ then fail()
+ | (Ast0.DECL(decl1),Ast0.CODE(code2)) ->
+ let v1 = is_decl decl1 in
+ let v2 = List.for_all is_toplevel (Ast0.undots code2) in
+ if !Flag.make_hrule = None && v1 && not v2 then fail()
+ | (Ast0.CODE(code1),Ast0.DECL(decl2)) ->
+ let v1 = List.for_all is_toplevel (Ast0.undots code1) in
+ let v2 = is_decl decl2 in
+ if v1 && not v2 then fail()
+ | (Ast0.CODE(code1),Ast0.CODE(code2)) ->
+ let testers = [is_exp;is_ty] in
+ List.iter
+ (function tester ->
+ let v1 = isonly tester code1 in
+ let v2 = isonly tester code2 in
+ if (v1 && not v2) or (!Flag.make_hrule = None && v2 && not v1)
+ then fail())
+ testers;
+ let v1 = isonly is_fndecl code1 in
+ let v2 = List.for_all is_toplevel (Ast0.undots code2) in
+ if !Flag.make_hrule = None && v1 && not v2 then fail()
+ | (Ast0.FILEINFO(_,_),Ast0.FILEINFO(_,_)) -> ()
+ | (Ast0.OTHER(_),Ast0.OTHER(_)) -> ()
+ | _ -> fail()
+
+(* ------------------------------------------------------------------- *)
+
+(* returns a list of corresponding minus and plus trees *)
+let context_neg minus plus =
+ Hashtbl.clear minus_table;
+ Hashtbl.clear plus_table;
+ List.iter contextify_whencode minus;
+ let (minus,plus) = realign minus plus in
+ let rec loop = function
+ ([],[]) -> []
+ | ([],l) ->
+ failwith (Printf.sprintf "%d plus things remaining" (List.length l))
+ | (minus,[]) ->
+ plus_lines := [];
+ let _ =
+ List.map
+ (function m ->
+ classify true
+ (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+ minus_table m)
+ minus in
+ []
+ | (((m::minus) as mall),((p::plus) as pall)) ->
+ let minfo = Ast0.get_info m in
+ let pinfo = Ast0.get_info p in
+ let mstart = minfo.Ast0.logical_start in
+ let mend = minfo.Ast0.logical_end in
+ let pstart = pinfo.Ast0.logical_start in
+ let pend = pinfo.Ast0.logical_end in
+ if (iscode m or iscode p) &&
+ (mend + 1 = pstart or pend + 1 = mstart or (* adjacent *)
+ (mstart <= pstart && mend >= pstart) or
+ (pstart <= mstart && pend >= mstart)) (* overlapping or nested *)
+ then
+ begin
+ (* ensure that the root of each tree has a unique index,
+ although it might get overwritten if the node is a context
+ node *)
+ let i = Ast0.fresh_index() in
+ Ast0.set_index m i; Ast0.set_index p i;
+ check_compatible m p;
+ collect_plus_lines p;
+ let _ =
+ classify true
+ (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+ minus_table m in
+ let _ = classify false (function _ -> Ast0.PLUS) plus_table p in
+ traverse minus_table plus_table;
+ (m,p)::loop(minus,plus)
+ end
+ else
+ if not(iscode m or iscode p)
+ then loop(minus,plus)
+ else
+ if mstart < pstart
+ then
+ begin
+ plus_lines := [];
+ let _ =
+ classify true
+ (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+ minus_table m in
+ loop(minus,pall)
+ end
+ else loop(mall,plus) in
+ loop(minus,plus)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Detects subtrees that are all minus/plus and nodes that are "binding
+context nodes". The latter is a node whose structure and immediate tokens
+are the same in the minus and plus trees, and such that for every child,
+the set of context nodes in the child subtree is the same in the minus and
+plus subtrees. *)
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+module U = Unparse_ast0
+
+(* --------------------------------------------------------------------- *)
+(* Generic access to code *)
+
+let set_mcodekind x mcodekind =
+ match x with
+ Ast0.DotsExprTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsInitTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsParamTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsStmtTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsDeclTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DotsCaseTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.IdentTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.ExprTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.ParamTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.DeclTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.InitTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.StmtTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.CaseLineTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.TopTag(d) -> Ast0.set_mcodekind d mcodekind
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+
+let set_index x index =
+ match x with
+ Ast0.DotsExprTag(d) -> Ast0.set_index d index
+ | Ast0.DotsInitTag(d) -> Ast0.set_index d index
+ | Ast0.DotsParamTag(d) -> Ast0.set_index d index
+ | Ast0.DotsStmtTag(d) -> Ast0.set_index d index
+ | Ast0.DotsDeclTag(d) -> Ast0.set_index d index
+ | Ast0.DotsCaseTag(d) -> Ast0.set_index d index
+ | Ast0.IdentTag(d) -> Ast0.set_index d index
+ | Ast0.ExprTag(d) -> Ast0.set_index d index
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Ast0.set_index d index
+ | Ast0.ParamTag(d) -> Ast0.set_index d index
+ | Ast0.InitTag(d) -> Ast0.set_index d index
+ | Ast0.DeclTag(d) -> Ast0.set_index d index
+ | Ast0.StmtTag(d) -> Ast0.set_index d index
+ | Ast0.CaseLineTag(d) -> Ast0.set_index d index
+ | Ast0.TopTag(d) -> Ast0.set_index d index
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+
+let get_index = function
+ Ast0.DotsExprTag(d) -> Index.expression_dots d
+ | Ast0.DotsInitTag(d) -> Index.initialiser_dots d
+ | Ast0.DotsParamTag(d) -> Index.parameter_dots d
+ | Ast0.DotsStmtTag(d) -> Index.statement_dots d
+ | Ast0.DotsDeclTag(d) -> Index.declaration_dots d
+ | Ast0.DotsCaseTag(d) -> Index.case_line_dots d
+ | Ast0.IdentTag(d) -> Index.ident d
+ | Ast0.ExprTag(d) -> Index.expression d
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Index.typeC d
+ | Ast0.ParamTag(d) -> Index.parameterTypeDef d
+ | Ast0.InitTag(d) -> Index.initialiser d
+ | Ast0.DeclTag(d) -> Index.declaration d
+ | Ast0.StmtTag(d) -> Index.statement d
+ | Ast0.CaseLineTag(d) -> Index.case_line d
+ | Ast0.TopTag(d) -> Index.top_level d
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+
+(* --------------------------------------------------------------------- *)
+(* Collect the line numbers of the plus code. This is used for disjunctions.
+It is not completely clear why this is necessary, but it seems like an easy
+fix for whatever is the problem that is discussed in disj_cases *)
+
+let plus_lines = ref ([] : int list)
+
+let insert n =
+ let rec loop = function
+ [] -> [n]
+ | x::xs ->
+ match compare n x with
+ 1 -> x::(loop xs)
+ | 0 -> x::xs
+ | -1 -> n::x::xs
+ | _ -> failwith "not possible" in
+ plus_lines := loop !plus_lines
+
+let find n min max =
+ let rec loop = function
+ [] -> (min,max)
+ | [x] -> if n < x then (min,x) else (x,max)
+ | x1::x2::rest ->
+ if n < x1
+ then (min,x1)
+ else if n > x1 && n < x2 then (x1,x2) else loop (x2::rest) in
+ loop !plus_lines
+
+let collect_plus_lines top =
+ plus_lines := [];
+ let bind x y = () in
+ let option_default = () in
+ let donothing r k e = k e in
+ let mcode (_,_,info,mcodekind,_) =
+ match mcodekind with
+ Ast0.PLUS -> insert info.Ast0.line_start
+ | _ -> () in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing in
+ fn.V0.combiner_top_level top
+
+(* --------------------------------------------------------------------- *)
+
+type kind = Neutral | AllMarked | NotAllMarked (* marked means + or - *)
+
+(* --------------------------------------------------------------------- *)
+(* The first part analyzes each of the minus tree and the plus tree
+separately *)
+
+(* ints are unique token indices (offset field) *)
+type node =
+ Token (* tokens *) of kind * int (* unique index *) * Ast0.mcodekind *
+ int list (* context tokens *)
+ | Recursor (* children *) of kind *
+ int list (* indices of all tokens at the level below *) *
+ Ast0.mcodekind list (* tokens at the level below *) *
+ int list
+ | Bind (* neighbors *) of kind *
+ int list (* indices of all tokens at current level *) *
+ Ast0.mcodekind list (* tokens at current level *) *
+ int list (* indices of all tokens at the level below *) *
+ Ast0.mcodekind list (* tokens at the level below *)
+ * int list list
+
+let kind2c = function
+ Neutral -> "neutral"
+ | AllMarked -> "allmarked"
+ | NotAllMarked -> "notallmarked"
+
+let node2c = function
+ Token(k,_,_,_) -> Printf.sprintf "token %s\n" (kind2c k)
+ | Recursor(k,_,_,_) -> Printf.sprintf "recursor %s\n" (kind2c k)
+ | Bind(k,_,_,_,_,_) -> Printf.sprintf "bind %s\n" (kind2c k)
+
+(* goal: detect negative in both tokens and recursors, or context only in
+tokens *)
+let bind c1 c2 =
+ let lub = function
+ (k1,k2) when k1 = k2 -> k1
+ | (Neutral,AllMarked) -> AllMarked
+ | (AllMarked,Neutral) -> AllMarked
+ | _ -> NotAllMarked in
+ match (c1,c2) with
+ (* token/token *)
+ (* there are tokens at this level, so ignore the level below *)
+ (Token(k1,i1,t1,l1),Token(k2,i2,t2,l2)) ->
+ Bind(lub(k1,k2),[i1;i2],[t1;t2],[],[],[l1;l2])
+
+ (* token/recursor *)
+ (* there are tokens at this level, so ignore the level below *)
+ | (Token(k1,i1,t1,l1),Recursor(k2,_,_,l2)) ->
+ Bind(lub(k1,k2),[i1],[t1],[],[],[l1;l2])
+ | (Recursor(k1,_,_,l1),Token(k2,i2,t2,l2)) ->
+ Bind(lub(k1,k2),[i2],[t2],[],[],[l1;l2])
+
+ (* token/bind *)
+ (* there are tokens at this level, so ignore the level below *)
+ | (Token(k1,i1,t1,l1),Bind(k2,i2,t2,_,_,l2)) ->
+ Bind(lub(k1,k2),i1::i2,t1::t2,[],[],l1::l2)
+ | (Bind(k1,i1,t1,_,_,l1),Token(k2,i2,t2,l2)) ->
+ Bind(lub(k1,k2),i1@[i2],t1@[t2],[],[],l1@[l2])
+
+ (* recursor/bind *)
+ | (Recursor(k1,bi1,bt1,l1),Bind(k2,i2,t2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),i2,t2,bi1@bi2,bt1@bt2,l1::l2)
+ | (Bind(k1,i1,t1,bi1,bt1,l1),Recursor(k2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),i1,t1,bi1@bi2,bt1@bt2,l1@[l2])
+
+ (* recursor/recursor and bind/bind - not likely to ever occur *)
+ | (Recursor(k1,bi1,bt1,l1),Recursor(k2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),[],[],bi1@bi2,bt1@bt2,[l1;l2])
+ | (Bind(k1,i1,t1,bi1,bt1,l1),Bind(k2,i2,t2,bi2,bt2,l2)) ->
+ Bind(lub(k1,k2),i1@i2,t1@t2,bi1@bi2,bt1@bt2,l1@l2)
+
+
+let option_default = (*Bind(Neutral,[],[],[],[],[])*)
+ Recursor(Neutral,[],[],[])
+
+let mcode (_,_,info,mcodekind,pos) =
+ let offset = info.Ast0.offset in
+ match mcodekind with
+ Ast0.MINUS(_) -> Token(AllMarked,offset,mcodekind,[])
+ | Ast0.PLUS -> Token(AllMarked,offset,mcodekind,[])
+ | Ast0.CONTEXT(_) -> Token(NotAllMarked,offset,mcodekind,[offset])
+ | _ -> failwith "not possible"
+
+let neutral_mcode (_,_,info,mcodekind,pos) =
+ let offset = info.Ast0.offset in
+ match mcodekind with
+ Ast0.MINUS(_) -> Token(Neutral,offset,mcodekind,[])
+ | Ast0.PLUS -> Token(Neutral,offset,mcodekind,[])
+ | Ast0.CONTEXT(_) -> Token(Neutral,offset,mcodekind,[offset])
+ | _ -> failwith "not possible"
+
+let is_context = function Ast0.CONTEXT(_) -> true | _ -> false
+
+let union_all l = List.fold_left Common.union_set [] l
+
+(* is minus is true when we are processing minus code that might be
+intermingled with plus code. it is used in disj_cases *)
+let classify is_minus all_marked table code =
+ let mkres builder k il tl bil btl l e =
+ (if k = AllMarked
+ then Ast0.set_mcodekind e (all_marked()) (* definitive *)
+ else
+ let check_index il tl =
+ if List.for_all is_context tl
+ then
+ (let e1 = builder e in
+ let index = (get_index e1)@il in
+ try
+ let _ = Hashtbl.find table index in
+ failwith
+ (Printf.sprintf "%d: index %s already used\n"
+ (Ast0.get_info e).Ast0.line_start
+ (String.concat " " (List.map string_of_int index)))
+ with Not_found -> Hashtbl.add table index (e1,l)) in
+ if il = [] then check_index bil btl else check_index il tl);
+ if il = []
+ then Recursor(k, bil, btl, union_all l)
+ else Recursor(k, il, tl, union_all l) in
+
+ let compute_result builder e = function
+ Bind(k,il,tl,bil,btl,l) -> mkres builder k il tl bil btl l e
+ | Token(k,il,tl,l) -> mkres builder k [il] [tl] [] [] [l] e
+ | Recursor(k,bil,btl,l) -> mkres builder k [] [] bil btl [l] e in
+
+ let make_not_marked = function
+ Bind(k,il,tl,bil,btl,l) -> Bind(NotAllMarked,il,tl,bil,btl,l)
+ | Token(k,il,tl,l) -> Token(NotAllMarked,il,tl,l)
+ | Recursor(k,bil,btl,l) -> Recursor(NotAllMarked,bil,btl,l) in
+
+ let do_nothing builder r k e = compute_result builder e (k e) in
+
+ let disj_cases disj starter code fn ender =
+ (* neutral_mcode used so starter and ender don't have an affect on
+ whether the code is considered all plus/minus, but so that they are
+ consider in the index list, which is needed to make a disj with
+ something in one branch and nothing in the other different from code
+ that just has the something (starter/ender enough, mids not needed
+ for this). Cannot agglomerate + code over | boundaries, because two -
+ cases might have different + code, and don't want to put the + code
+ together into one unit. *)
+ let make_not_marked =
+ if is_minus
+ then
+ (let min = Ast0.get_line disj in
+ let max = Ast0.get_line_end disj in
+ let (plus_min,plus_max) = find min (min-1) (max+1) in
+ if max > plus_max then make_not_marked else (function x -> x))
+ else make_not_marked in
+ bind (neutral_mcode starter)
+ (bind (List.fold_right bind
+ (List.map make_not_marked (List.map fn code))
+ option_default)
+ (neutral_mcode ender)) in
+
+ (* no whencode in plus tree so have to drop it *)
+ (* need special cases for dots, nests, and disjs *)
+ let expression r k e =
+ compute_result Ast0.expr e
+ (match Ast0.unwrap e with
+ Ast0.NestExpr(starter,exp,ender,whencode,multi) ->
+ k (Ast0.rewrap e (Ast0.NestExpr(starter,exp,ender,None,multi)))
+ | Ast0.Edots(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Edots(dots,None)))
+ | Ast0.Ecircles(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Ecircles(dots,None)))
+ | Ast0.Estars(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Estars(dots,None)))
+ | Ast0.DisjExpr(starter,expr_list,_,ender) ->
+ disj_cases e starter expr_list r.V0.combiner_expression ender
+ | _ -> k e) in
+
+ (* not clear why we have the next two cases, since DisjDecl and
+ DisjType shouldn't have been constructed yet, as they only come from isos *)
+ let declaration r k e =
+ compute_result Ast0.decl e
+ (match Ast0.unwrap e with
+ Ast0.DisjDecl(starter,decls,_,ender) ->
+ disj_cases e starter decls r.V0.combiner_declaration ender
+ | Ast0.Ddots(dots,whencode) ->
+ k (Ast0.rewrap e (Ast0.Ddots(dots,None)))
+ (* Need special cases for the following so that the type will be
+ considered as a unit, rather than distributed around the
+ declared variable. This needs to be done because of the call to
+ compute_result, ie the processing of each term should make a
+ side-effect on the complete term structure as well as collecting
+ some information about it. So we have to visit each complete
+ term structure. In (all?) other such cases, we visit the terms
+ using rebuilder, which just visits the subterms, rather than
+ reordering their components. *)
+ | Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ bind (match stg with Some stg -> mcode stg | _ -> option_default)
+ (bind (r.V0.combiner_typeC ty)
+ (bind (r.V0.combiner_ident id)
+ (bind (mcode eq)
+ (bind (r.V0.combiner_initialiser ini) (mcode sem)))))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ bind (match stg with Some stg -> mcode stg | _ -> option_default)
+ (bind (r.V0.combiner_typeC ty)
+ (bind (r.V0.combiner_ident id) (mcode sem)))
+ | _ -> k e) in
+
+ let param r k e =
+ compute_result Ast0.param e
+ (match Ast0.unwrap e with
+ Ast0.Param(ty,Some id) ->
+ (* needed for the same reason as in the Init and UnInit cases *)
+ bind (r.V0.combiner_typeC ty) (r.V0.combiner_ident id)
+ | _ -> k e) in
+
+ let typeC r k e =
+ compute_result Ast0.typeC e
+ (match Ast0.unwrap e with
+ Ast0.DisjType(starter,types,_,ender) ->
+ disj_cases e starter types r.V0.combiner_typeC ender
+ | _ -> k e) in
+
+ let initialiser r k i =
+ compute_result Ast0.ini i
+ (match Ast0.unwrap i with
+ Ast0.Idots(dots,whencode) ->
+ k (Ast0.rewrap i (Ast0.Idots(dots,None)))
+ | _ -> k i) in
+
+ let statement r k s =
+ compute_result Ast0.stmt s
+ (match Ast0.unwrap s with
+ Ast0.Nest(started,stm_dots,ender,whencode,multi) ->
+ k (Ast0.rewrap s (Ast0.Nest(started,stm_dots,ender,[],multi)))
+ | Ast0.Dots(dots,whencode) ->
+ k (Ast0.rewrap s (Ast0.Dots(dots,[])))
+ | Ast0.Circles(dots,whencode) ->
+ k (Ast0.rewrap s (Ast0.Circles(dots,[])))
+ | Ast0.Stars(dots,whencode) ->
+ k (Ast0.rewrap s (Ast0.Stars(dots,[])))
+ | Ast0.Disj(starter,statement_dots_list,_,ender) ->
+ disj_cases s starter statement_dots_list r.V0.combiner_statement_dots
+ ender
+(* Why? There is nothing there
+ (* cases for everything with extra mcode *)
+ | Ast0.FunDecl((info,bef),_,_,_,_,_,_,_,_)
+ | Ast0.Decl((info,bef),_) ->
+ bind (mcode ((),(),info,bef)) (k s)
+ | Ast0.IfThen(_,_,_,_,_,(info,aft))
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft))
+ | Ast0.While(_,_,_,_,_,(info,aft)) ->
+ | Ast0.For(_,_,_,_,_,_,_,_,_,(info,aft)) ->
+ bind (k s) (mcode ((),(),info,aft))
+ | Ast0.Iterator(_,_,_,_,_,(info,aft))
+*)
+ | _ -> k s
+
+) in
+
+ let do_top builder r k e = compute_result builder e (k e) in
+
+ let combiner =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ (do_nothing Ast0.dotsExpr) (do_nothing Ast0.dotsInit)
+ (do_nothing Ast0.dotsParam) (do_nothing Ast0.dotsStmt)
+ (do_nothing Ast0.dotsDecl) (do_nothing Ast0.dotsCase)
+ (do_nothing Ast0.ident) expression typeC initialiser param declaration
+ statement (do_nothing Ast0.case_line) (do_top Ast0.top) in
+ combiner.V0.combiner_top_level code
+
+(* --------------------------------------------------------------------- *)
+(* Traverse the hash tables and find corresponding context nodes that have
+the same context children *)
+
+(* this is just a sanity check - really only need to look at the top-level
+ structure *)
+let equal_mcode (_,_,info1,_,_) (_,_,info2,_,_) =
+ info1.Ast0.offset = info2.Ast0.offset
+
+let equal_option e1 e2 =
+ match (e1,e2) with
+ (Some x, Some y) -> equal_mcode x y
+ | (None, None) -> true
+ | _ -> false
+
+let dots fn d1 d2 =
+ match (Ast0.unwrap d1,Ast0.unwrap d2) with
+ (Ast0.DOTS(l1),Ast0.DOTS(l2)) -> List.length l1 = List.length l2
+ | (Ast0.CIRCLES(l1),Ast0.CIRCLES(l2)) -> List.length l1 = List.length l2
+ | (Ast0.STARS(l1),Ast0.STARS(l2)) -> List.length l1 = List.length l2
+ | _ -> false
+
+let rec equal_ident i1 i2 =
+ match (Ast0.unwrap i1,Ast0.unwrap i2) with
+ (Ast0.Id(name1),Ast0.Id(name2)) -> equal_mcode name1 name2
+ | (Ast0.MetaId(name1,_,_),Ast0.MetaId(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.MetaFunc(name1,_,_),Ast0.MetaFunc(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.MetaLocalFunc(name1,_,_),Ast0.MetaLocalFunc(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.OptIdent(_),Ast0.OptIdent(_)) -> true
+ | (Ast0.UniqueIdent(_),Ast0.UniqueIdent(_)) -> true
+ | _ -> false
+
+let rec equal_expression e1 e2 =
+ match (Ast0.unwrap e1,Ast0.unwrap e2) with
+ (Ast0.Ident(_),Ast0.Ident(_)) -> true
+ | (Ast0.Constant(const1),Ast0.Constant(const2)) -> equal_mcode const1 const2
+ | (Ast0.FunCall(_,lp1,_,rp1),Ast0.FunCall(_,lp2,_,rp2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.Assignment(_,op1,_,_),Ast0.Assignment(_,op2,_,_)) ->
+ equal_mcode op1 op2
+ | (Ast0.CondExpr(_,why1,_,colon1,_),Ast0.CondExpr(_,why2,_,colon2,_)) ->
+ equal_mcode why1 why2 && equal_mcode colon1 colon2
+ | (Ast0.Postfix(_,op1),Ast0.Postfix(_,op2)) -> equal_mcode op1 op2
+ | (Ast0.Infix(_,op1),Ast0.Infix(_,op2)) -> equal_mcode op1 op2
+ | (Ast0.Unary(_,op1),Ast0.Unary(_,op2)) -> equal_mcode op1 op2
+ | (Ast0.Binary(_,op1,_),Ast0.Binary(_,op2,_)) -> equal_mcode op1 op2
+ | (Ast0.Paren(lp1,_,rp1),Ast0.Paren(lp2,_,rp2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.ArrayAccess(_,lb1,_,rb1),Ast0.ArrayAccess(_,lb2,_,rb2)) ->
+ equal_mcode lb1 lb2 && equal_mcode rb1 rb2
+ | (Ast0.RecordAccess(_,pt1,_),Ast0.RecordAccess(_,pt2,_)) ->
+ equal_mcode pt1 pt2
+ | (Ast0.RecordPtAccess(_,ar1,_),Ast0.RecordPtAccess(_,ar2,_)) ->
+ equal_mcode ar1 ar2
+ | (Ast0.Cast(lp1,_,rp1,_),Ast0.Cast(lp2,_,rp2,_)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.SizeOfExpr(szf1,_),Ast0.SizeOfExpr(szf2,_)) ->
+ equal_mcode szf1 szf2
+ | (Ast0.SizeOfType(szf1,lp1,_,rp1),Ast0.SizeOfType(szf2,lp2,_,rp2)) ->
+ equal_mcode szf1 szf2 && equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.TypeExp(_),Ast0.TypeExp(_)) -> true
+ | (Ast0.MetaErr(name1,_,_),Ast0.MetaErr(name2,_,_))
+ | (Ast0.MetaExpr(name1,_,_,_,_),Ast0.MetaExpr(name2,_,_,_,_))
+ | (Ast0.MetaExprList(name1,_,_),Ast0.MetaExprList(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.EComma(cm1),Ast0.EComma(cm2)) -> equal_mcode cm1 cm2
+ | (Ast0.DisjExpr(starter1,_,mids1,ender1),
+ Ast0.DisjExpr(starter2,_,mids2,ender2)) ->
+ equal_mcode starter1 starter2 &&
+ List.for_all2 equal_mcode mids1 mids2 &&
+ equal_mcode ender1 ender2
+ | (Ast0.NestExpr(starter1,_,ender1,_,m1),
+ Ast0.NestExpr(starter2,_,ender2,_,m2)) ->
+ equal_mcode starter1 starter2 && equal_mcode ender1 ender2 && m1 = m2
+ | (Ast0.Edots(dots1,_),Ast0.Edots(dots2,_))
+ | (Ast0.Ecircles(dots1,_),Ast0.Ecircles(dots2,_))
+ | (Ast0.Estars(dots1,_),Ast0.Estars(dots2,_)) -> equal_mcode dots1 dots2
+ | (Ast0.OptExp(_),Ast0.OptExp(_)) -> true
+ | (Ast0.UniqueExp(_),Ast0.UniqueExp(_)) -> true
+ | _ -> false
+
+let rec equal_typeC t1 t2 =
+ match (Ast0.unwrap t1,Ast0.unwrap t2) with
+ (Ast0.ConstVol(cv1,_),Ast0.ConstVol(cv2,_)) -> equal_mcode cv1 cv2
+ | (Ast0.BaseType(ty1,sign1),Ast0.BaseType(ty2,sign2)) ->
+ equal_mcode ty1 ty2 && equal_option sign1 sign2
+ | (Ast0.ImplicitInt(sign1),Ast0.ImplicitInt(sign2)) ->
+ equal_mcode sign1 sign2
+ | (Ast0.Pointer(_,star1),Ast0.Pointer(_,star2)) ->
+ equal_mcode star1 star2
+ | (Ast0.Array(_,lb1,_,rb1),Ast0.Array(_,lb2,_,rb2)) ->
+ equal_mcode lb1 lb2 && equal_mcode rb1 rb2
+ | (Ast0.StructUnionName(kind1,_),Ast0.StructUnionName(kind2,_)) ->
+ equal_mcode kind1 kind2
+ | (Ast0.FunctionType(ty1,lp1,p1,rp1),Ast0.FunctionType(ty2,lp2,p2,rp2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.StructUnionDef(_,lb1,_,rb1),
+ Ast0.StructUnionDef(_,lb2,_,rb2)) ->
+ equal_mcode lb1 lb2 && equal_mcode rb1 rb2
+ | (Ast0.TypeName(name1),Ast0.TypeName(name2)) -> equal_mcode name1 name2
+ | (Ast0.MetaType(name1,_),Ast0.MetaType(name2,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.DisjType(starter1,_,mids1,ender1),
+ Ast0.DisjType(starter2,_,mids2,ender2)) ->
+ equal_mcode starter1 starter2 &&
+ List.for_all2 equal_mcode mids1 mids2 &&
+ equal_mcode ender1 ender2
+ | (Ast0.OptType(_),Ast0.OptType(_)) -> true
+ | (Ast0.UniqueType(_),Ast0.UniqueType(_)) -> true
+ | _ -> false
+
+let equal_declaration d1 d2 =
+ match (Ast0.unwrap d1,Ast0.unwrap d2) with
+ (Ast0.Init(stg1,_,_,eq1,_,sem1),Ast0.Init(stg2,_,_,eq2,_,sem2)) ->
+ equal_option stg1 stg2 && equal_mcode eq1 eq2 && equal_mcode sem1 sem2
+ | (Ast0.UnInit(stg1,_,_,sem1),Ast0.UnInit(stg2,_,_,sem2)) ->
+ equal_option stg1 stg2 && equal_mcode sem1 sem2
+ | (Ast0.MacroDecl(nm1,lp1,_,rp1,sem1),Ast0.MacroDecl(nm2,lp2,_,rp2,sem2)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode sem1 sem2
+ | (Ast0.TyDecl(_,sem1),Ast0.TyDecl(_,sem2)) -> equal_mcode sem1 sem2
+ | (Ast0.Ddots(dots1,_),Ast0.Ddots(dots2,_)) -> equal_mcode dots1 dots2
+ | (Ast0.OptDecl(_),Ast0.OptDecl(_)) -> true
+ | (Ast0.UniqueDecl(_),Ast0.UniqueDecl(_)) -> true
+ | (Ast0.DisjDecl _,_) | (_,Ast0.DisjDecl _) ->
+ failwith "DisjDecl not expected here"
+ | _ -> false
+
+let equal_initialiser i1 i2 =
+ match (Ast0.unwrap i1,Ast0.unwrap i2) with
+ (Ast0.InitExpr(_),Ast0.InitExpr(_)) -> true
+ | (Ast0.InitList(lb1,_,rb1),Ast0.InitList(lb2,_,rb2)) ->
+ (equal_mcode lb1 lb2) && (equal_mcode rb1 rb2)
+ | (Ast0.InitGccDotName(dot1,_,eq1,_),Ast0.InitGccDotName(dot2,_,eq2,_)) ->
+ (equal_mcode dot1 dot2) && (equal_mcode eq1 eq2)
+ | (Ast0.InitGccName(_,eq1,_),Ast0.InitGccName(_,eq2,_)) ->
+ equal_mcode eq1 eq2
+ | (Ast0.InitGccIndex(lb1,_,rb1,eq1,_),Ast0.InitGccIndex(lb2,_,rb2,eq2,_)) ->
+ (equal_mcode lb1 lb2) && (equal_mcode rb1 rb2) && (equal_mcode eq1 eq2)
+ | (Ast0.InitGccRange(lb1,_,dots1,_,rb1,eq1,_),
+ Ast0.InitGccRange(lb2,_,dots2,_,rb2,eq2,_)) ->
+ (equal_mcode lb1 lb2) && (equal_mcode dots1 dots2) &&
+ (equal_mcode rb1 rb2) && (equal_mcode eq1 eq2)
+ | (Ast0.IComma(cm1),Ast0.IComma(cm2)) -> equal_mcode cm1 cm2
+ | (Ast0.Idots(d1,_),Ast0.Idots(d2,_)) -> equal_mcode d1 d2
+ | (Ast0.OptIni(_),Ast0.OptIni(_)) -> true
+ | (Ast0.UniqueIni(_),Ast0.UniqueIni(_)) -> true
+ | _ -> false
+
+let equal_parameterTypeDef p1 p2 =
+ match (Ast0.unwrap p1,Ast0.unwrap p2) with
+ (Ast0.VoidParam(_),Ast0.VoidParam(_)) -> true
+ | (Ast0.Param(_,_),Ast0.Param(_,_)) -> true
+ | (Ast0.MetaParam(name1,_),Ast0.MetaParam(name2,_))
+ | (Ast0.MetaParamList(name1,_,_),Ast0.MetaParamList(name2,_,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.PComma(cm1),Ast0.PComma(cm2)) -> equal_mcode cm1 cm2
+ | (Ast0.Pdots(dots1),Ast0.Pdots(dots2))
+ | (Ast0.Pcircles(dots1),Ast0.Pcircles(dots2)) -> equal_mcode dots1 dots2
+ | (Ast0.OptParam(_),Ast0.OptParam(_)) -> true
+ | (Ast0.UniqueParam(_),Ast0.UniqueParam(_)) -> true
+ | _ -> false
+
+let rec equal_statement s1 s2 =
+ match (Ast0.unwrap s1,Ast0.unwrap s2) with
+ (Ast0.FunDecl(_,fninfo1,_,lp1,_,rp1,lbrace1,_,rbrace1),
+ Ast0.FunDecl(_,fninfo2,_,lp2,_,rp2,lbrace2,_,rbrace2)) ->
+ (List.length fninfo1) = (List.length fninfo2) &&
+ List.for_all2 equal_fninfo fninfo1 fninfo2 &&
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 &&
+ equal_mcode lbrace1 lbrace2 && equal_mcode rbrace1 rbrace2
+ | (Ast0.Decl(_,_),Ast0.Decl(_,_)) -> true
+ | (Ast0.Seq(lbrace1,_,rbrace1),Ast0.Seq(lbrace2,_,rbrace2)) ->
+ equal_mcode lbrace1 lbrace2 && equal_mcode rbrace1 rbrace2
+ | (Ast0.ExprStatement(_,sem1),Ast0.ExprStatement(_,sem2)) ->
+ equal_mcode sem1 sem2
+ | (Ast0.IfThen(iff1,lp1,_,rp1,_,_),Ast0.IfThen(iff2,lp2,_,rp2,_,_)) ->
+ equal_mcode iff1 iff2 && equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.IfThenElse(iff1,lp1,_,rp1,_,els1,_,_),
+ Ast0.IfThenElse(iff2,lp2,_,rp2,_,els2,_,_)) ->
+ equal_mcode iff1 iff2 &&
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode els1 els2
+ | (Ast0.While(whl1,lp1,_,rp1,_,_),Ast0.While(whl2,lp2,_,rp2,_,_)) ->
+ equal_mcode whl1 whl2 && equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.Do(d1,_,whl1,lp1,_,rp1,sem1),Ast0.Do(d2,_,whl2,lp2,_,rp2,sem2)) ->
+ equal_mcode whl1 whl2 && equal_mcode d1 d2 &&
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode sem1 sem2
+ | (Ast0.For(fr1,lp1,_,sem11,_,sem21,_,rp1,_,_),
+ Ast0.For(fr2,lp2,_,sem12,_,sem22,_,rp2,_,_)) ->
+ equal_mcode fr1 fr2 && equal_mcode lp1 lp2 &&
+ equal_mcode sem11 sem12 && equal_mcode sem21 sem22 &&
+ equal_mcode rp1 rp2
+ | (Ast0.Iterator(nm1,lp1,_,rp1,_,_),Ast0.Iterator(nm2,lp2,_,rp2,_,_)) ->
+ equal_mcode lp1 lp2 && equal_mcode rp1 rp2
+ | (Ast0.Switch(switch1,lp1,_,rp1,lb1,case1,rb1),
+ Ast0.Switch(switch2,lp2,_,rp2,lb2,case2,rb2)) ->
+ equal_mcode switch1 switch2 && equal_mcode lp1 lp2 &&
+ equal_mcode rp1 rp2 && equal_mcode lb1 lb2 &&
+ equal_mcode rb1 rb2
+ | (Ast0.Break(br1,sem1),Ast0.Break(br2,sem2)) ->
+ equal_mcode br1 br2 && equal_mcode sem1 sem2
+ | (Ast0.Continue(cont1,sem1),Ast0.Continue(cont2,sem2)) ->
+ equal_mcode cont1 cont2 && equal_mcode sem1 sem2
+ | (Ast0.Label(_,dd1),Ast0.Label(_,dd2)) ->
+ equal_mcode dd1 dd2
+ | (Ast0.Goto(g1,_,sem1),Ast0.Goto(g2,_,sem2)) ->
+ equal_mcode g1 g2 && equal_mcode sem1 sem2
+ | (Ast0.Return(ret1,sem1),Ast0.Return(ret2,sem2)) ->
+ equal_mcode ret1 ret2 && equal_mcode sem1 sem2
+ | (Ast0.ReturnExpr(ret1,_,sem1),Ast0.ReturnExpr(ret2,_,sem2)) ->
+ equal_mcode ret1 ret2 && equal_mcode sem1 sem2
+ | (Ast0.MetaStmt(name1,_),Ast0.MetaStmt(name2,_))
+ | (Ast0.MetaStmtList(name1,_),Ast0.MetaStmtList(name2,_)) ->
+ equal_mcode name1 name2
+ | (Ast0.Disj(starter1,_,mids1,ender1),Ast0.Disj(starter2,_,mids2,ender2)) ->
+ equal_mcode starter1 starter2 &&
+ List.for_all2 equal_mcode mids1 mids2 &&
+ equal_mcode ender1 ender2
+ | (Ast0.Nest(starter1,_,ender1,_,m1),Ast0.Nest(starter2,_,ender2,_,m2)) ->
+ equal_mcode starter1 starter2 && equal_mcode ender1 ender2 && m1 = m2
+ | (Ast0.Exp(_),Ast0.Exp(_)) -> true
+ | (Ast0.TopExp(_),Ast0.TopExp(_)) -> true
+ | (Ast0.Ty(_),Ast0.Ty(_)) -> true
+ | (Ast0.Dots(d1,_),Ast0.Dots(d2,_))
+ | (Ast0.Circles(d1,_),Ast0.Circles(d2,_))
+ | (Ast0.Stars(d1,_),Ast0.Stars(d2,_)) -> equal_mcode d1 d2
+ | (Ast0.Include(inc1,name1),Ast0.Include(inc2,name2)) ->
+ equal_mcode inc1 inc2 && equal_mcode name1 name2
+ | (Ast0.Define(def1,_,_,_),Ast0.Define(def2,_,_,_)) ->
+ equal_mcode def1 def2
+ | (Ast0.OptStm(_),Ast0.OptStm(_)) -> true
+ | (Ast0.UniqueStm(_),Ast0.UniqueStm(_)) -> true
+ | _ -> false
+
+and equal_fninfo x y =
+ match (x,y) with
+ (Ast0.FStorage(s1),Ast0.FStorage(s2)) -> equal_mcode s1 s2
+ | (Ast0.FType(_),Ast0.FType(_)) -> true
+ | (Ast0.FInline(i1),Ast0.FInline(i2)) -> equal_mcode i1 i2
+ | (Ast0.FAttr(i1),Ast0.FAttr(i2)) -> equal_mcode i1 i2
+ | _ -> false
+
+let equal_case_line c1 c2 =
+ match (Ast0.unwrap c1,Ast0.unwrap c2) with
+ (Ast0.Default(def1,colon1,_),Ast0.Default(def2,colon2,_)) ->
+ equal_mcode def1 def2 && equal_mcode colon1 colon2
+ | (Ast0.Case(case1,_,colon1,_),Ast0.Case(case2,_,colon2,_)) ->
+ equal_mcode case1 case2 && equal_mcode colon1 colon2
+ | (Ast0.OptCase(_),Ast0.OptCase(_)) -> true
+ | _ -> false
+
+let rec equal_top_level t1 t2 =
+ match (Ast0.unwrap t1,Ast0.unwrap t2) with
+ (Ast0.DECL(_),Ast0.DECL(_)) -> true
+ | (Ast0.FILEINFO(old_file1,new_file1),Ast0.FILEINFO(old_file2,new_file2)) ->
+ equal_mcode old_file1 old_file2 && equal_mcode new_file1 new_file2
+ | (Ast0.CODE(_),Ast0.CODE(_)) -> true
+ | (Ast0.ERRORWORDS(_),Ast0.ERRORWORDS(_)) -> true
+ | _ -> false
+
+let root_equal e1 e2 =
+ match (e1,e2) with
+ (Ast0.DotsExprTag(d1),Ast0.DotsExprTag(d2)) -> dots equal_expression d1 d2
+ | (Ast0.DotsParamTag(d1),Ast0.DotsParamTag(d2)) ->
+ dots equal_parameterTypeDef d1 d2
+ | (Ast0.DotsStmtTag(d1),Ast0.DotsStmtTag(d2)) -> dots equal_statement d1 d2
+ | (Ast0.DotsDeclTag(d1),Ast0.DotsDeclTag(d2)) -> dots equal_declaration d1 d2
+ | (Ast0.DotsCaseTag(d1),Ast0.DotsCaseTag(d2)) -> dots equal_case_line d1 d2
+ | (Ast0.IdentTag(i1),Ast0.IdentTag(i2)) -> equal_ident i1 i2
+ | (Ast0.ExprTag(e1),Ast0.ExprTag(e2)) -> equal_expression e1 e2
+ | (Ast0.ArgExprTag(d),_) -> failwith "not possible - iso only"
+ | (Ast0.TypeCTag(t1),Ast0.TypeCTag(t2)) -> equal_typeC t1 t2
+ | (Ast0.ParamTag(p1),Ast0.ParamTag(p2)) -> equal_parameterTypeDef p1 p2
+ | (Ast0.InitTag(d1),Ast0.InitTag(d2)) -> equal_initialiser d1 d2
+ | (Ast0.DeclTag(d1),Ast0.DeclTag(d2)) -> equal_declaration d1 d2
+ | (Ast0.StmtTag(s1),Ast0.StmtTag(s2)) -> equal_statement s1 s2
+ | (Ast0.TopTag(t1),Ast0.TopTag(t2)) -> equal_top_level t1 t2
+ | (Ast0.IsoWhenTag(_),_) | (_,Ast0.IsoWhenTag(_))
+ | (Ast0.IsoWhenTTag(_),_) | (_,Ast0.IsoWhenTTag(_))
+ | (Ast0.IsoWhenFTag(_),_) | (_,Ast0.IsoWhenFTag(_)) ->
+ failwith "only within iso phase"
+ | _ -> false
+
+let default_context _ =
+ Ast0.CONTEXT(ref(Ast.NOTHING,
+ Ast0.default_token_info,Ast0.default_token_info))
+
+let traverse minus_table plus_table =
+ Hashtbl.iter
+ (function key ->
+ function (e,l) ->
+ try
+ let (plus_e,plus_l) = Hashtbl.find plus_table key in
+ if root_equal e plus_e &&
+ List.for_all (function x -> x)
+ (List.map2 Common.equal_set l plus_l)
+ then
+ let i = Ast0.fresh_index() in
+ (set_index e i; set_index plus_e i;
+ set_mcodekind e (default_context());
+ set_mcodekind plus_e (default_context()))
+ with Not_found -> ())
+ minus_table
+
+(* --------------------------------------------------------------------- *)
+(* contextify the whencode *)
+
+let contextify_all =
+ let bind x y = () in
+ let option_default = () in
+ let mcode x = () in
+ let do_nothing r k e = Ast0.set_mcodekind e (default_context()); k e in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing do_nothing do_nothing
+
+let contextify_whencode =
+ let bind x y = () in
+ let option_default = () in
+ let mcode x = () in
+ let do_nothing r k e = k e in
+
+ let expression r k e =
+ k e;
+ match Ast0.unwrap e with
+ Ast0.NestExpr(_,_,_,Some whencode,_)
+ | Ast0.Edots(_,Some whencode)
+ | Ast0.Ecircles(_,Some whencode)
+ | Ast0.Estars(_,Some whencode) ->
+ contextify_all.V0.combiner_expression whencode
+ | _ -> () in
+
+ let initialiser r k i =
+ match Ast0.unwrap i with
+ Ast0.Idots(dots,Some whencode) ->
+ contextify_all.V0.combiner_initialiser whencode
+ | _ -> k i in
+
+ let whencode = function
+ Ast0.WhenNot sd -> contextify_all.V0.combiner_statement_dots sd
+ | Ast0.WhenAlways s -> contextify_all.V0.combiner_statement s
+ | Ast0.WhenModifier(_) -> ()
+ | Ast0.WhenNotTrue(e) -> contextify_all.V0.combiner_expression e
+ | Ast0.WhenNotFalse(e) -> contextify_all.V0.combiner_expression e in
+
+ let statement r k (s : Ast0.statement) =
+ k s;
+ match Ast0.unwrap s with
+ Ast0.Nest(_,_,_,whn,_)
+ | Ast0.Dots(_,whn) | Ast0.Circles(_,whn) | Ast0.Stars(_,whn) ->
+ List.iter whencode whn
+ | _ -> () in
+
+ let combiner =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
+ do_nothing
+ expression
+ do_nothing initialiser do_nothing do_nothing statement do_nothing
+ do_nothing in
+ combiner.V0.combiner_top_level
+
+(* --------------------------------------------------------------------- *)
+
+(* the first int list is the tokens in the node, the second is the tokens
+in the descendents *)
+let minus_table =
+ (Hashtbl.create(50) : (int list, Ast0.anything * int list list) Hashtbl.t)
+let plus_table =
+ (Hashtbl.create(50) : (int list, Ast0.anything * int list list) Hashtbl.t)
+
+let iscode t =
+ match Ast0.unwrap t with
+ Ast0.DECL(_) -> true
+ | Ast0.FILEINFO(_) -> true
+ | Ast0.ERRORWORDS(_) -> false
+ | Ast0.CODE(_) -> true
+ | Ast0.OTHER(_) -> failwith "unexpected top level code"
+
+(* ------------------------------------------------------------------- *)
+(* alignment of minus and plus *)
+
+let concat = function
+ [] -> []
+ | [s] -> [s]
+ | l ->
+ let rec loop = function
+ [] -> []
+ | x::rest ->
+ (match Ast0.unwrap x with
+ Ast0.DECL(s) -> let stms = loop rest in s::stms
+ | Ast0.CODE(ss) ->
+ let stms = loop rest in
+ (match Ast0.unwrap ss with
+ Ast0.DOTS(d) -> d@stms
+ | _ -> failwith "no dots allowed in pure plus code")
+ | _ -> failwith "plus code is being discarded") in
+ let res =
+ Compute_lines.statement_dots
+ (Ast0.rewrap (List.hd l) (Ast0.DOTS (loop l))) in
+ [Ast0.rewrap res (Ast0.CODE res)]
+
+let collect_up_to m plus =
+ let minfo = Ast0.get_info m in
+ let mend = minfo.Ast0.logical_end in
+ let rec loop = function
+ [] -> ([],[])
+ | p::plus ->
+ let pinfo = Ast0.get_info p in
+ let pstart = pinfo.Ast0.logical_start in
+ if pstart > mend
+ then ([],p::plus)
+ else let (plus,rest) = loop plus in (p::plus,rest) in
+ let (plus,rest) = loop plus in
+ (concat plus,rest)
+
+let realign minus plus =
+ let rec loop = function
+ ([],_) -> failwith "not possible, some context required"
+ | ([m],p) -> ([m],concat p)
+ | (m::minus,plus) ->
+ let (p,plus) = collect_up_to m plus in
+ let (minus,plus) = loop (minus,plus) in
+ (m::minus,p@plus) in
+ loop (minus,plus)
+
+(* ------------------------------------------------------------------- *)
+(* check compatible: check that at the top level the minus and plus code is
+of the same kind. Could go further and make the correspondence between the
+code between ...s. *)
+
+let isonly f l = match Ast0.undots l with [s] -> f s | _ -> false
+
+let isall f l = List.for_all (isonly f) l
+
+let rec is_exp s =
+ match Ast0.unwrap s with
+ Ast0.Exp(e) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_exp stmts
+ | _ -> false
+
+let rec is_ty s =
+ match Ast0.unwrap s with
+ Ast0.Ty(e) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_ty stmts
+ | _ -> false
+
+let rec is_decl s =
+ match Ast0.unwrap s with
+ Ast0.Decl(_,e) -> true
+ | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_decl stmts
+ | _ -> false
+
+let rec is_fndecl s =
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_fndecl stmts
+ | _ -> false
+
+let rec is_toplevel s =
+ match Ast0.unwrap s with
+ Ast0.Decl(_,e) -> true
+ | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
+ | Ast0.Disj(_,stmts,_,_) -> isall is_toplevel stmts
+ | Ast0.ExprStatement(fc,_) ->
+ (match Ast0.unwrap fc with
+ Ast0.FunCall(_,_,_,_) -> true
+ | _ -> false)
+ | Ast0.Include(_,_) -> true
+ | Ast0.Define(_,_,_,_) -> true
+ | _ -> false
+
+let check_compatible m p =
+ let fail _ =
+ failwith
+ (Printf.sprintf
+ "incompatible minus and plus code starting on lines %d and %d"
+ (Ast0.get_line m) (Ast0.get_line p)) in
+ match (Ast0.unwrap m, Ast0.unwrap p) with
+ (Ast0.DECL(decl1),Ast0.DECL(decl2)) ->
+ if not (is_decl decl1 && is_decl decl2)
+ then fail()
+ | (Ast0.DECL(decl1),Ast0.CODE(code2)) ->
+ let v1 = is_decl decl1 in
+ let v2 = List.for_all is_toplevel (Ast0.undots code2) in
+ if !Flag.make_hrule = None && v1 && not v2 then fail()
+ | (Ast0.CODE(code1),Ast0.DECL(decl2)) ->
+ let v1 = List.for_all is_toplevel (Ast0.undots code1) in
+ let v2 = is_decl decl2 in
+ if v1 && not v2 then fail()
+ | (Ast0.CODE(code1),Ast0.CODE(code2)) ->
+ let testers = [is_exp;is_ty] in
+ List.iter
+ (function tester ->
+ let v1 = isonly tester code1 in
+ let v2 = isonly tester code2 in
+ if (v1 && not v2) or (!Flag.make_hrule = None && v2 && not v1)
+ then fail())
+ testers;
+ let v1 = isonly is_fndecl code1 in
+ let v2 = List.for_all is_toplevel (Ast0.undots code2) in
+ if !Flag.make_hrule = None && v1 && not v2 then fail()
+ | (Ast0.FILEINFO(_,_),Ast0.FILEINFO(_,_)) -> ()
+ | (Ast0.OTHER(_),Ast0.OTHER(_)) -> ()
+ | _ -> fail()
+
+(* ------------------------------------------------------------------- *)
+
+(* returns a list of corresponding minus and plus trees *)
+let context_neg minus plus =
+ Hashtbl.clear minus_table;
+ Hashtbl.clear plus_table;
+ List.iter contextify_whencode minus;
+ let (minus,plus) = realign minus plus in
+ let rec loop = function
+ ([],[]) -> []
+ | ([],l) ->
+ failwith (Printf.sprintf "%d plus things remaining" (List.length l))
+ | (minus,[]) ->
+ plus_lines := [];
+ let _ =
+ List.map
+ (function m ->
+ classify true
+ (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+ minus_table m)
+ minus in
+ []
+ | (((m::minus) as mall),((p::plus) as pall)) ->
+ let minfo = Ast0.get_info m in
+ let pinfo = Ast0.get_info p in
+ let mstart = minfo.Ast0.logical_start in
+ let mend = minfo.Ast0.logical_end in
+ let pstart = pinfo.Ast0.logical_start in
+ let pend = pinfo.Ast0.logical_end in
+ if (iscode m or iscode p) &&
+ (mend + 1 = pstart or pend + 1 = mstart or (* adjacent *)
+ (mstart <= pstart && mend >= pstart) or
+ (pstart <= mstart && pend >= mstart)) (* overlapping or nested *)
+ then
+ begin
+ (* ensure that the root of each tree has a unique index,
+ although it might get overwritten if the node is a context
+ node *)
+ let i = Ast0.fresh_index() in
+ Ast0.set_index m i; Ast0.set_index p i;
+ check_compatible m p;
+ collect_plus_lines p;
+ let _ =
+ classify true
+ (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+ minus_table m in
+ let _ = classify false (function _ -> Ast0.PLUS) plus_table p in
+ traverse minus_table plus_table;
+ (m,p)::loop(minus,plus)
+ end
+ else
+ if not(iscode m or iscode p)
+ then loop(minus,plus)
+ else
+ if mstart < pstart
+ then
+ begin
+ plus_lines := [];
+ let _ =
+ classify true
+ (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+ minus_table m in
+ loop(minus,pall)
+ end
+ else loop(mall,plus) in
+ loop(minus,plus)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+module V = Visitor_ast
+
+let disjmult2 e1 e2 k =
+ List.concat
+ (List.map (function e1 -> List.map (function e2 -> k e1 e2) e2) e1)
+
+let disjmult3 e1 e2 e3 k =
+ List.concat
+ (List.map
+ (function e1 ->
+ List.concat
+ (List.map
+ (function e2 -> List.map (function e3 -> k e1 e2 e3) e3)
+ e2))
+ e1)
+
+let rec disjmult f = function
+ [] -> [[]]
+ | x::xs ->
+ let cur = f x in
+ let rest = disjmult f xs in
+ disjmult2 cur rest (function cur -> function rest -> cur :: rest)
+
+let disjoption f = function
+ None -> [None]
+ | Some x -> List.map (function x -> Some x) (f x)
+
+let disjdots f d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) ->
+ List.map (function l -> Ast.rewrap d (Ast.DOTS(l))) (disjmult f l)
+ | Ast.CIRCLES(l) ->
+ List.map (function l -> Ast.rewrap d (Ast.CIRCLES(l))) (disjmult f l)
+ | Ast.STARS(l) ->
+ List.map (function l -> Ast.rewrap d (Ast.STARS(l))) (disjmult f l)
+
+let rec disjty ft =
+ match Ast.unwrap ft with
+ Ast.Type(cv,ty) ->
+ let ty = disjtypeC ty in
+ List.map (function ty -> Ast.rewrap ft (Ast.Type(cv,ty))) ty
+ | Ast.DisjType(types) -> List.concat (List.map disjty types)
+ | Ast.OptType(ty) ->
+ let ty = disjty ty in
+ List.map (function ty -> Ast.rewrap ft (Ast.OptType(ty))) ty
+ | Ast.UniqueType(ty) ->
+ let ty = disjty ty in
+ List.map (function ty -> Ast.rewrap ft (Ast.UniqueType(ty))) ty
+
+and disjtypeC bty =
+ match Ast.unwrap bty with
+ Ast.BaseType(_,_) | Ast.ImplicitInt(_) -> [bty]
+ | Ast.Pointer(ty,star) ->
+ let ty = disjty ty in
+ List.map (function ty -> Ast.rewrap bty (Ast.Pointer(ty,star))) ty
+ | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ let ty = disjty ty in
+ List.map
+ (function ty ->
+ Ast.rewrap bty (Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2)))
+ ty
+ | Ast.FunctionType (s,ty,lp1,params,rp1) ->
+ let ty = disjoption disjty ty in
+ List.map
+ (function ty ->
+ Ast.rewrap bty (Ast.FunctionType (s,ty,lp1,params,rp1)))
+ ty
+ | Ast.Array(ty,lb,size,rb) ->
+ disjmult2 (disjty ty) (disjoption disjexp size)
+ (function ty -> function size ->
+ Ast.rewrap bty (Ast.Array(ty,lb,size,rb)))
+ | Ast.StructUnionName(kind,name) -> [bty]
+ | Ast.StructUnionDef(ty,lb,decls,rb) ->
+ disjmult2 (disjty ty) (disjdots disjdecl decls)
+ (function ty -> function decls ->
+ Ast.rewrap bty (Ast.StructUnionDef(ty,lb,decls,rb)))
+ | Ast.TypeName(_) | Ast.MetaType(_,_,_) -> [bty]
+
+and disjexp e =
+ match Ast.unwrap e with
+ Ast.Ident(_) | Ast.Constant(_) -> [e]
+ | Ast.FunCall(fn,lp,args,rp) ->
+ disjmult2 (disjexp fn) (disjdots disjexp args)
+ (function fn -> function args ->
+ Ast.rewrap e (Ast.FunCall(fn,lp,args,rp)))
+ | Ast.Assignment(left,op,right,simple) ->
+ disjmult2 (disjexp left) (disjexp right)
+ (function left -> function right ->
+ Ast.rewrap e (Ast.Assignment(left,op,right,simple)))
+ | Ast.CondExpr(exp1,why,Some exp2,colon,exp3) ->
+ let res = disjmult disjexp [exp1;exp2;exp3] in
+ List.map
+ (function
+ [exp1;exp2;exp3] ->
+ Ast.rewrap e (Ast.CondExpr(exp1,why,Some exp2,colon,exp3))
+ | _ -> failwith "not possible")
+ res
+ | Ast.CondExpr(exp1,why,None,colon,exp3) ->
+ disjmult2 (disjexp exp1) (disjexp exp3)
+ (function exp1 -> function exp3 ->
+ Ast.rewrap e (Ast.CondExpr(exp1,why,None,colon,exp3)))
+ | Ast.Postfix(exp,op) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.Postfix(exp,op))) exp
+ | Ast.Infix(exp,op) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.Infix(exp,op))) exp
+ | Ast.Unary(exp,op) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.Unary(exp,op))) exp
+ | Ast.Binary(left,op,right) ->
+ disjmult2 (disjexp left) (disjexp right)
+ (function left -> function right ->
+ Ast.rewrap e (Ast.Binary(left,op,right)))
+ | Ast.Nested(exp,op,right) ->
+ (* disj not possible in right *)
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.Nested(exp,op,right))) exp
+ | Ast.Paren(lp,exp,rp) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.Paren(lp,exp,rp))) exp
+ | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
+ disjmult2 (disjexp exp1) (disjexp exp2)
+ (function exp1 -> function exp2 ->
+ Ast.rewrap e (Ast.ArrayAccess(exp1,lb,exp2,rb)))
+ | Ast.RecordAccess(exp,pt,field) ->
+ let exp = disjexp exp in
+ List.map
+ (function exp -> Ast.rewrap e (Ast.RecordAccess(exp,pt,field))) exp
+ | Ast.RecordPtAccess(exp,ar,field) ->
+ let exp = disjexp exp in
+ List.map
+ (function exp -> Ast.rewrap e (Ast.RecordPtAccess(exp,ar,field))) exp
+ | Ast.Cast(lp,ty,rp,exp) ->
+ disjmult2 (disjty ty) (disjexp exp)
+ (function ty -> function exp -> Ast.rewrap e (Ast.Cast(lp,ty,rp,exp)))
+ | Ast.SizeOfExpr(szf,exp) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.SizeOfExpr(szf,exp))) exp
+ | Ast.SizeOfType(szf,lp,ty,rp) ->
+ let ty = disjty ty in
+ List.map
+ (function ty -> Ast.rewrap e (Ast.SizeOfType(szf,lp,ty,rp))) ty
+ | Ast.TypeExp(ty) ->
+ let ty = disjty ty in
+ List.map (function ty -> Ast.rewrap e (Ast.TypeExp(ty))) ty
+ | Ast.MetaErr(_,_,_,_) | Ast.MetaExpr(_,_,_,_,_,_)
+ | Ast.MetaExprList(_,_,_,_) | Ast.EComma(_) -> [e]
+ | Ast.DisjExpr(exp_list) -> List.concat (List.map disjexp exp_list)
+ | Ast.NestExpr(expr_dots,whencode,multi) ->
+ (* not sure what to do here, so ambiguities still possible *)
+ [e]
+ | Ast.Edots(dots,_) | Ast.Ecircles(dots,_) | Ast.Estars(dots,_) -> [e]
+ | Ast.OptExp(exp) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.OptExp(exp))) exp
+ | Ast.UniqueExp(exp) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap e (Ast.UniqueExp(exp))) exp
+
+and disjparam p =
+ match Ast.unwrap p with
+ Ast.VoidParam(ty) -> [p] (* void is the only possible value *)
+ | Ast.Param(ty,id) ->
+ let ty = disjty ty in
+ List.map (function ty -> Ast.rewrap p (Ast.Param(ty,id))) ty
+ | Ast.MetaParam(_,_,_) | Ast.MetaParamList(_,_,_,_) | Ast.PComma(_) -> [p]
+ | Ast.Pdots(dots) | Ast.Pcircles(dots) -> [p]
+ | Ast.OptParam(param) ->
+ let param = disjparam param in
+ List.map (function param -> Ast.rewrap p (Ast.OptParam(param))) param
+ | Ast.UniqueParam(param) ->
+ let param = disjparam param in
+ List.map (function param -> Ast.rewrap p (Ast.UniqueParam(param))) param
+
+and disjini i =
+ match Ast.unwrap i with
+ Ast.InitExpr(exp) ->
+ let exp = disjexp exp in
+ List.map (function exp -> Ast.rewrap i (Ast.InitExpr(exp))) exp
+ | Ast.InitList(lb,initlist,rb,whencode) ->
+ List.map
+ (function initlist ->
+ Ast.rewrap i (Ast.InitList(lb,initlist,rb,whencode)))
+ (disjmult disjini initlist)
+ | Ast.InitGccDotName(dot,name,eq,ini) ->
+ let ini = disjini ini in
+ List.map
+ (function ini -> Ast.rewrap i (Ast.InitGccDotName(dot,name,eq,ini)))
+ ini
+ | Ast.InitGccName(name,eq,ini) ->
+ let ini = disjini ini in
+ List.map
+ (function ini -> Ast.rewrap i (Ast.InitGccName(name,eq,ini)))
+ ini
+ | Ast.InitGccIndex(lb,exp,rb,eq,ini) ->
+ disjmult2 (disjexp exp) (disjini ini)
+ (function exp -> function ini ->
+ Ast.rewrap i (Ast.InitGccIndex(lb,exp,rb,eq,ini)))
+ | Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ disjmult3 (disjexp exp1) (disjexp exp2) (disjini ini)
+ (function exp1 -> function exp2 -> function ini ->
+ Ast.rewrap i (Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini)))
+ | Ast.IComma(comma) -> [i]
+ | Ast.OptIni(ini) ->
+ let ini = disjini ini in
+ List.map (function ini -> Ast.rewrap i (Ast.OptIni(ini))) ini
+ | Ast.UniqueIni(ini) ->
+ let ini = disjini ini in
+ List.map (function ini -> Ast.rewrap i (Ast.UniqueIni(ini))) ini
+
+and disjdecl d =
+ match Ast.unwrap d with
+ Ast.Init(stg,ty,id,eq,ini,sem) ->
+ disjmult2 (disjty ty) (disjini ini)
+ (function ty -> function ini ->
+ Ast.rewrap d (Ast.Init(stg,ty,id,eq,ini,sem)))
+ | Ast.UnInit(stg,ty,id,sem) ->
+ let ty = disjty ty in
+ List.map (function ty -> Ast.rewrap d (Ast.UnInit(stg,ty,id,sem))) ty
+ | Ast.MacroDecl(name,lp,args,rp,sem) ->
+ List.map
+ (function args -> Ast.rewrap d (Ast.MacroDecl(name,lp,args,rp,sem)))
+ (disjdots disjexp args)
+ | Ast.TyDecl(ty,sem) ->
+ let ty = disjty ty in
+ List.map (function ty -> Ast.rewrap d (Ast.TyDecl(ty,sem))) ty
+ | Ast.Typedef(stg,ty,id,sem) ->
+ let ty = disjty ty in (* disj not allowed in id *)
+ List.map (function ty -> Ast.rewrap d (Ast.Typedef(stg,ty,id,sem))) ty
+ | Ast.DisjDecl(decls) -> List.concat (List.map disjdecl decls)
+ | Ast.Ddots(_,_) | Ast.MetaDecl(_,_,_) -> [d]
+ | Ast.OptDecl(decl) ->
+ let decl = disjdecl decl in
+ List.map (function decl -> Ast.rewrap d (Ast.OptDecl(decl))) decl
+ | Ast.UniqueDecl(decl) ->
+ let decl = disjdecl decl in
+ List.map (function decl -> Ast.rewrap d (Ast.UniqueDecl(decl))) decl
+
+let generic_orify_rule_elem f re exp rebuild =
+ match f exp with
+ [exp] -> re
+ | orexps -> Ast.rewrap re (Ast.DisjRuleElem (List.map rebuild orexps))
+
+let orify_rule_elem re exp rebuild =
+ generic_orify_rule_elem disjexp re exp rebuild
+
+let orify_rule_elem_ty = generic_orify_rule_elem disjty
+let orify_rule_elem_param = generic_orify_rule_elem disjparam
+let orify_rule_elem_decl = generic_orify_rule_elem disjdecl
+
+let disj_rule_elem r k re =
+ match Ast.unwrap re with
+ Ast.FunHeader(bef,allminus,fninfo,name,lp,params,rp) ->
+ generic_orify_rule_elem (disjdots disjparam) re params
+ (function params ->
+ Ast.rewrap re
+ (Ast.FunHeader(bef,allminus,fninfo,name,lp,params,rp)))
+ | Ast.Decl(bef,allminus,decl) ->
+ orify_rule_elem_decl re decl
+ (function decl -> Ast.rewrap re (Ast.Decl(bef,allminus,decl)))
+ | Ast.SeqStart(brace) -> re
+ | Ast.SeqEnd(brace) -> re
+ | Ast.ExprStatement(exp,sem) ->
+ orify_rule_elem re exp
+ (function exp -> Ast.rewrap re (Ast.ExprStatement(exp,sem)))
+ | Ast.IfHeader(iff,lp,exp,rp) ->
+ orify_rule_elem re exp
+ (function exp -> Ast.rewrap re (Ast.IfHeader(iff,lp,exp,rp)))
+ | Ast.Else(els) -> re
+ | Ast.WhileHeader(whl,lp,exp,rp) ->
+ orify_rule_elem re exp
+ (function exp -> Ast.rewrap re (Ast.WhileHeader(whl,lp,exp,rp)))
+ | Ast.DoHeader(d) -> re
+ | Ast.WhileTail(whl,lp,exp,rp,sem) ->
+ orify_rule_elem re exp
+ (function exp -> Ast.rewrap re (Ast.WhileTail(whl,lp,exp,rp,sem)))
+ | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
+ generic_orify_rule_elem (disjmult (disjoption disjexp)) re [e1;e2;e3]
+ (function
+ [exp1;exp2;exp3] ->
+ Ast.rewrap re (Ast.ForHeader(fr,lp,exp1,sem1,exp2,sem2,exp3,rp))
+ | _ -> failwith "not possible")
+ | Ast.IteratorHeader(whl,lp,args,rp) ->
+ generic_orify_rule_elem (disjdots disjexp) re args
+ (function args -> Ast.rewrap re (Ast.IteratorHeader(whl,lp,args,rp)))
+ | Ast.SwitchHeader(switch,lp,exp,rp) ->
+ orify_rule_elem re exp
+ (function exp -> Ast.rewrap re (Ast.SwitchHeader(switch,lp,exp,rp)))
+ | Ast.Break(_,_) | Ast.Continue(_,_) | Ast.Label(_,_) | Ast.Goto(_,_,_)
+ | Ast.Return(_,_) -> re
+ | Ast.ReturnExpr(ret,exp,sem) ->
+ orify_rule_elem re exp
+ (function exp -> Ast.rewrap re (Ast.ReturnExpr(ret,exp,sem)))
+ | Ast.MetaRuleElem(_,_,_) | Ast.MetaStmt(_,_,_,_)
+ | Ast.MetaStmtList(_,_,_) -> re
+ | Ast.Exp(exp) ->
+ orify_rule_elem re exp (function exp -> Ast.rewrap exp (Ast.Exp(exp)))
+ | Ast.TopExp(exp) ->
+ orify_rule_elem re exp (function exp -> Ast.rewrap exp (Ast.TopExp(exp)))
+ | Ast.Ty(ty) ->
+ orify_rule_elem_ty re ty (function ty -> Ast.rewrap ty (Ast.Ty(ty)))
+ | Ast.Include(inc,s) -> re
+ | Ast.DefineHeader(def,id,params) -> re
+ | Ast.Default(def,colon) -> re
+ | Ast.Case(case,exp,colon) ->
+ orify_rule_elem re exp
+ (function exp -> Ast.rewrap re (Ast.Case(case,exp,colon)))
+ | Ast.DisjRuleElem(_) -> failwith "not possible"
+
+let disj_all =
+ let mcode x = x in
+ let donothing r k e = k e in
+ V.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ disj_rule_elem donothing donothing donothing donothing
+
+(* ----------------------------------------------------------------------- *)
+(* collect iso information at the rule_elem level *)
+
+let collect_all_isos =
+ let bind = (@) in
+ let option_default = [] in
+ let mcode r x = [] in
+ let donothing r k e = Common.union_set (Ast.get_isos e) (k e) in
+ let doanything r k e = k e in
+ V.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing doanything
+
+let collect_iso_info =
+ let mcode x = x in
+ let donothing r k e = k e in
+ let rule_elem r k e =
+ match Ast.unwrap e with
+ Ast.DisjRuleElem(l) -> k e
+ | _ ->
+ let isos = collect_all_isos.V.combiner_rule_elem e in
+ Ast.set_isos e isos in
+ V.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing rule_elem donothing donothing
+ donothing donothing
+
+(* ----------------------------------------------------------------------- *)
+
+let disj rules =
+ List.map
+ (function (mv,r) ->
+ match r with
+ Ast.ScriptRule _ -> (mv, r)
+ | Ast.CocciRule (nm, rule_info, r, isexp) ->
+ let res =
+ List.map
+ (function x ->
+ let res = disj_all.V.rebuilder_top_level x in
+ if !Flag.track_iso_usage
+ then collect_iso_info.V.rebuilder_top_level res
+ else res)
+ r in
+ (mv, Ast.CocciRule (nm,rule_info,res,isexp)))
+ rules
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* create an index for each constructor *)
+(* current max is 145 *)
+
+(* doesn't really work - requires that identical terms with no token
+subterms (eg dots) not appear on the same line *)
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+
+(* if a dot list is empty, add the starting line of the dot list to the
+address. Otherwise add 0. An empty dot list should only match with another
+empty one. *)
+let expression_dots d =
+ let ln = (Ast0.get_info d).Ast0.line_start in
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> 1::(if l = [] then [ln] else [0])
+ | Ast0.CIRCLES(l) -> 2::(if l = [] then [ln] else [0])
+ | Ast0.STARS(l) -> 3::(if l = [] then [ln] else [0])
+
+let initialiser_dots d =
+ let ln = (Ast0.get_info d).Ast0.line_start in
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> 113::(if l = [] then [ln] else [0])
+ | Ast0.CIRCLES(l) -> 114::(if l = [] then [ln] else [0])
+ | Ast0.STARS(l) -> 115::(if l = [] then [ln] else [0])
+
+let parameter_dots d =
+ let ln = (Ast0.get_info d).Ast0.line_start in
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> 4::(if l = [] then [ln] else [0])
+ | Ast0.CIRCLES(l) -> 5::(if l = [] then [ln] else [0])
+ | Ast0.STARS(l) -> 6::(if l = [] then [ln] else [0])
+
+let statement_dots d =
+ let ln = (Ast0.get_info d).Ast0.line_start in
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> 7::(if l = [] then [ln] else [0])
+ | Ast0.CIRCLES(l) -> 8::(if l = [] then [ln] else [0])
+ | Ast0.STARS(l) -> 9::(if l = [] then [ln] else [0])
+
+let declaration_dots d =
+ let ln = (Ast0.get_info d).Ast0.line_start in
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> 134::(if l = [] then [ln] else [0])
+ | Ast0.CIRCLES(l) -> 135::(if l = [] then [ln] else [0])
+ | Ast0.STARS(l) -> 136::(if l = [] then [ln] else [0])
+
+let case_line_dots d =
+ let ln = (Ast0.get_info d).Ast0.line_start in
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> 138::(if l = [] then [ln] else [0])
+ | Ast0.CIRCLES(l) -> 139::(if l = [] then [ln] else [0])
+ | Ast0.STARS(l) -> 140::(if l = [] then [ln] else [0])
+
+let ident i =
+ match Ast0.unwrap i with
+ Ast0.Id(name) -> [10]
+ | Ast0.MetaId(name,_,_) -> [11]
+ | Ast0.MetaFunc(name,_,_) -> [12]
+ | Ast0.MetaLocalFunc(name,_,_) -> [13]
+ | Ast0.OptIdent(id) -> [14]
+ | Ast0.UniqueIdent(id) -> [15]
+
+let expression e =
+ match Ast0.unwrap e with
+ Ast0.Ident(id) -> [17]
+ | Ast0.Constant(const) -> [18]
+ | Ast0.FunCall(fn,lp,args,rp) -> [19]
+ | Ast0.Assignment(left,op,right,simple) -> [20]
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) -> [21]
+ | Ast0.Postfix(exp,op) -> [22]
+ | Ast0.Infix(exp,op) -> [23]
+ | Ast0.Unary(exp,op) -> [24]
+ | Ast0.Binary(left,op,right) -> [25]
+ | Ast0.Nested(left,op,right) -> failwith "nested in index not possible"
+ | Ast0.Paren(lp,exp,rp) -> [26]
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) -> [27]
+ | Ast0.RecordAccess(exp,pt,field) -> [28]
+ | Ast0.RecordPtAccess(exp,ar,field) -> [29]
+ | Ast0.Cast(lp,ty,rp,exp) -> [30]
+ | Ast0.SizeOfExpr(szf,exp) -> [98] (* added after *)
+ | Ast0.SizeOfType(szf,lp,ty,rp) -> [99] (* added after *)
+ | Ast0.TypeExp(ty) -> [123] (* added after *)
+ | Ast0.MetaErr(name,_,_) -> [32]
+ | Ast0.MetaExpr(name,_,ty,_,_) -> [33]
+ | Ast0.MetaExprList(name,_,_) -> [34]
+ | Ast0.EComma(cm) -> [35]
+ | Ast0.DisjExpr(_,expr_list,_,_) -> [36]
+ | Ast0.NestExpr(_,expr_dots,_,_,_) -> [37]
+ | Ast0.Edots(dots,whencode) -> [38]
+ | Ast0.Ecircles(dots,whencode) -> [39]
+ | Ast0.Estars(dots,whencode) -> [40]
+ | Ast0.OptExp(exp) -> [41]
+ | Ast0.UniqueExp(exp) -> [42]
+
+let typeC t =
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> [44]
+ | Ast0.BaseType(ty,sign) -> [48]
+ | Ast0.ImplicitInt(sign) -> [129]
+ | Ast0.Pointer(ty,star) -> [49]
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> [131]
+ | Ast0.FunctionType(ty,lp1,params,rp1) -> [132]
+ | Ast0.Array(ty,lb,size,rb) -> [50]
+ | Ast0.StructUnionName(kind,name) -> [51]
+ | Ast0.StructUnionDef(ty,lb,decls,rb) -> [117]
+ | Ast0.TypeName(name) -> [52]
+ | Ast0.MetaType(name,_) -> [53]
+ | Ast0.DisjType(_,type_list,_,_) -> [130]
+ | Ast0.OptType(ty) -> [45]
+ | Ast0.UniqueType(ty) -> [46]
+
+let declaration d =
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,exp,sem) -> [54]
+ | Ast0.UnInit(stg,ty,id,sem) -> [55]
+ | Ast0.MacroDecl(name,lp,args,rp,sem) -> [137]
+ | Ast0.TyDecl(ty,sem) -> [116]
+ | Ast0.Typedef(stg,ty,id,sem) -> [143]
+ | Ast0.DisjDecl(_,decls,_,_) -> [97] (* added after *)
+ | Ast0.Ddots(dots,whencode) -> [133]
+ | Ast0.OptDecl(decl) -> [56]
+ | Ast0.UniqueDecl(decl) -> [57]
+
+let initialiser i =
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> [102] (* added after *)
+ | Ast0.InitList(lb,initlist,rb) -> [103]
+ | Ast0.InitGccDotName(dot,name,eq,ini) -> [104]
+ | Ast0.InitGccName(name,eq,ini) -> [105]
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) -> [106]
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) -> [107]
+ | Ast0.IComma(cm) -> [108]
+ | Ast0.Idots(d,whencode) -> [109]
+ | Ast0.OptIni(id) -> [110]
+ | Ast0.UniqueIni(id) -> [111]
+
+let parameterTypeDef p =
+ match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> [59]
+ | Ast0.Param(ty,id) -> [60]
+ | Ast0.MetaParam(name,_) -> [61]
+ | Ast0.MetaParamList(name,_,_) -> [62]
+ | Ast0.PComma(cm) -> [63]
+ | Ast0.Pdots(dots) -> [64]
+ | Ast0.Pcircles(dots) -> [65]
+ | Ast0.OptParam(param) -> [66]
+ | Ast0.UniqueParam(param) -> [67]
+
+let statement s =
+ match Ast0.unwrap s with
+ Ast0.FunDecl(bef,fninfo,name,lp,params,rp,lbrace,body,rbrace) -> [68]
+ | Ast0.Decl(bef,decl) -> [69]
+ | Ast0.Seq(lbrace,body,rbrace) -> [70]
+ | Ast0.ExprStatement(exp,sem) -> [71]
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,aft) -> [72]
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) -> [73]
+ | Ast0.While(whl,lp,exp,rp,body,_) -> [74]
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> [75]
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,_) -> [76]
+ | Ast0.Iterator(nm,lp,args,rp,body,_) -> [142]
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) -> [125]
+ | Ast0.Break(br,sem) -> [100]
+ | Ast0.Continue(cont,sem) -> [101]
+ | Ast0.Label(l,dd) -> [144]
+ | Ast0.Goto(goto,l,sem) -> [145]
+ | Ast0.Return(ret,sem) -> [77]
+ | Ast0.ReturnExpr(ret,exp,sem) -> [78]
+ | Ast0.MetaStmt(name,_) -> [79]
+ | Ast0.MetaStmtList(name,_) -> [80]
+ | Ast0.Disj(_,statement_dots_list,_,_) -> [81]
+ | Ast0.Nest(_,stmt_dots,_,_,_) -> [82]
+ | Ast0.Exp(exp) -> [83]
+ | Ast0.TopExp(exp) -> [141]
+ | Ast0.Ty(ty) -> [124]
+ | Ast0.Dots(d,whencode) -> [84]
+ | Ast0.Circles(d,whencode) -> [85]
+ | Ast0.Stars(d,whencode) -> [86]
+ | Ast0.Include(inc,name) -> [118]
+ | Ast0.Define(def,id,params,body) -> [119]
+ | Ast0.OptStm(re) -> [87]
+ | Ast0.UniqueStm(re) -> [88]
+
+let case_line c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) -> [126]
+ | Ast0.Case(case,exp,colon,code) -> [127]
+ | Ast0.OptCase(case) -> [128]
+
+let top_level t =
+ match Ast0.unwrap t with
+ Ast0.DECL(stmt) -> [90]
+ | Ast0.FILEINFO(old_file,new_file) -> [92]
+ | Ast0.CODE(stmt_dots) -> [94]
+ | Ast0.ERRORWORDS(exps) -> [95]
+ | Ast0.OTHER(_) -> [96]
+
+(* 99-101 already used *)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* The error message "no available token to attach to" often comes in an
+argument list of unbounded length. In this case, one should move a comma so
+that there is a comma after the + code. *)
+
+(* Start at all of the corresponding BindContext nodes in the minus and
+plus trees, and traverse their children. We take the same strategy as
+before: collect the list of minus/context nodes/tokens and the list of plus
+tokens, and then merge them. *)
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+module CN = Context_neg
+
+let get_option f = function
+ None -> []
+ | Some x -> f x
+
+(* --------------------------------------------------------------------- *)
+(* Collect root and all context nodes in a tree *)
+
+let collect_context e =
+ let bind x y = x @ y in
+ let option_default = [] in
+
+ let mcode _ = [] in
+
+ let donothing builder r k e =
+ match Ast0.get_mcodekind e with
+ Ast0.CONTEXT(_) -> (builder e) :: (k e)
+ | _ -> k e in
+
+(* special case for everything that contains whencode, so that we skip over
+it *)
+ let expression r k e =
+ donothing Ast0.expr r k
+ (Ast0.rewrap e
+ (match Ast0.unwrap e with
+ Ast0.NestExpr(starter,exp,ender,whencode,multi) ->
+ Ast0.NestExpr(starter,exp,ender,None,multi)
+ | Ast0.Edots(dots,whencode) -> Ast0.Edots(dots,None)
+ | Ast0.Ecircles(dots,whencode) -> Ast0.Ecircles(dots,None)
+ | Ast0.Estars(dots,whencode) -> Ast0.Estars(dots,None)
+ | e -> e)) in
+
+ let initialiser r k i =
+ donothing Ast0.ini r k
+ (Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.Idots(dots,whencode) -> Ast0.Idots(dots,None)
+ | i -> i)) in
+
+ let statement r k s =
+ donothing Ast0.stmt r k
+ (Ast0.rewrap s
+ (match Ast0.unwrap s with
+ Ast0.Nest(started,stm_dots,ender,whencode,multi) ->
+ Ast0.Nest(started,stm_dots,ender,[],multi)
+ | Ast0.Dots(dots,whencode) -> Ast0.Dots(dots,[])
+ | Ast0.Circles(dots,whencode) -> Ast0.Circles(dots,[])
+ | Ast0.Stars(dots,whencode) -> Ast0.Stars(dots,[])
+ | s -> s)) in
+
+ let topfn r k e = Ast0.TopTag(e) :: (k e) in
+
+ let res =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ (donothing Ast0.dotsExpr) (donothing Ast0.dotsInit)
+ (donothing Ast0.dotsParam) (donothing Ast0.dotsStmt)
+ (donothing Ast0.dotsDecl) (donothing Ast0.dotsCase)
+ (donothing Ast0.ident) expression (donothing Ast0.typeC) initialiser
+ (donothing Ast0.param) (donothing Ast0.decl) statement
+ (donothing Ast0.case_line) topfn in
+ res.V0.combiner_top_level e
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* collect the possible join points, in order, among the children of a
+BindContext. Dots are not allowed. Nests and disjunctions are no problem,
+because their delimiters take up a line by themselves *)
+
+(* An Unfavored token is one that is in a BindContext node; using this causes
+ the node to become Neither, meaning that isomorphisms can't be applied *)
+(* Toplevel is for the bef token of a function declaration and is for
+attaching top-level definitions that should come before the complete
+declaration *)
+type minus_join_point = Favored | Unfavored | Toplevel | Decl
+
+(* Maps the index of a node to the indices of the mcodes it contains *)
+let root_token_table = (Hashtbl.create(50) : (int, int list) Hashtbl.t)
+
+let create_root_token_table minus =
+ Hashtbl.iter
+ (function tokens ->
+ function (node,_) ->
+ let key =
+ match node with
+ Ast0.DotsExprTag(d) -> Ast0.get_index d
+ | Ast0.DotsInitTag(d) -> Ast0.get_index d
+ | Ast0.DotsParamTag(d) -> Ast0.get_index d
+ | Ast0.DotsStmtTag(d) -> Ast0.get_index d
+ | Ast0.DotsDeclTag(d) -> Ast0.get_index d
+ | Ast0.DotsCaseTag(d) -> Ast0.get_index d
+ | Ast0.IdentTag(d) -> Ast0.get_index d
+ | Ast0.ExprTag(d) -> Ast0.get_index d
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Ast0.get_index d
+ | Ast0.ParamTag(d) -> Ast0.get_index d
+ | Ast0.InitTag(d) -> Ast0.get_index d
+ | Ast0.DeclTag(d) -> Ast0.get_index d
+ | Ast0.StmtTag(d) -> Ast0.get_index d
+ | Ast0.CaseLineTag(d) -> Ast0.get_index d
+ | Ast0.TopTag(d) -> Ast0.get_index d
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+ in
+ Hashtbl.add root_token_table key tokens)
+ CN.minus_table;
+ List.iter
+ (function r ->
+ let index = Ast0.get_index r in
+ try let _ = Hashtbl.find root_token_table index in ()
+ with Not_found -> Hashtbl.add root_token_table index [])
+ minus
+
+let collect_minus_join_points root =
+ let root_index = Ast0.get_index root in
+ let unfavored_tokens = Hashtbl.find root_token_table root_index in
+ let bind x y = x @ y in
+ let option_default = [] in
+
+ let mcode (_,_,info,mcodekind,_) =
+ if List.mem (info.Ast0.offset) unfavored_tokens
+ then [(Unfavored,info,mcodekind)]
+ else [(Favored,info,mcodekind)] in
+
+ let do_nothing r k e =
+ let info = Ast0.get_info e in
+ let index = Ast0.get_index e in
+ match Ast0.get_mcodekind e with
+ (Ast0.MINUS(_)) as mc -> [(Favored,info,mc)]
+ | (Ast0.CONTEXT(_)) as mc when not(index = root_index) ->
+ (* This was unfavored at one point, but I don't remember why *)
+ [(Favored,info,mc)]
+ | _ -> k e in
+
+(* don't want to attach to the outside of DOTS, because metavariables can't
+bind to that; not good for isomorphisms *)
+
+ let dots f k d =
+ let multibind l =
+ let rec loop = function
+ [] -> option_default
+ | [x] -> x
+ | x::xs -> bind x (loop xs) in
+ loop l in
+
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> multibind (List.map f l)
+ | Ast0.CIRCLES(l) -> multibind (List.map f l)
+ | Ast0.STARS(l) -> multibind (List.map f l) in
+
+ let edots r k d = dots r.V0.combiner_expression k d in
+ let idots r k d = dots r.V0.combiner_initialiser k d in
+ let pdots r k d = dots r.V0.combiner_parameter k d in
+ let sdots r k d = dots r.V0.combiner_statement k d in
+ let ddots r k d = dots r.V0.combiner_declaration k d in
+ let cdots r k d = dots r.V0.combiner_case_line k d in
+
+ (* a case for everything that has a Opt *)
+
+ let statement r k s =
+ (*
+ let redo_branched res (ifinfo,aftmc) =
+ let redo fv info mc rest =
+ let new_info = {info with Ast0.attachable_end = false} in
+ List.rev ((Favored,ifinfo,aftmc)::(fv,new_info,mc)::rest) in
+ match List.rev res with
+ [(fv,info,mc)] ->
+ (match mc with
+ Ast0.MINUS(_) | Ast0.CONTEXT(_) ->
+ (* even for -, better for isos not to integrate code after an
+ if into the if body.
+ but the problem is that this can extend the region in
+ which a variable is bound, because a variable bound in the
+ aft node would seem to have to be live in the whole if,
+ whereas we might like it to be live in only one branch.
+ ie ideally, if we can keep the minus code in the right
+ order, we would like to drop it as close to the bindings
+ of its free variables. This could be anywhere in the minus
+ code. Perhaps we would like to do this after the
+ application of isomorphisms, though.
+ *)
+ redo fv info mc []
+ | _ -> res)
+ | (fv,info,mc)::rest ->
+ (match mc with
+ Ast0.CONTEXT(_) -> redo fv info mc rest
+ | _ -> res)
+ | _ -> failwith "unexpected empty code" in *)
+ match Ast0.unwrap s with
+ (* Ast0.IfThen(_,_,_,_,_,aft)
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,aft)
+ | Ast0.While(_,_,_,_,_,aft)
+ | Ast0.For(_,_,_,_,_,_,_,_,_,aft)
+ | Ast0.Iterator(_,_,_,_,_,aft) ->
+ redo_branched (do_nothing r k s) aft*)
+ | Ast0.FunDecl((info,bef),fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ (Toplevel,info,bef)::(k s)
+ | Ast0.Decl((info,bef),decl) -> (Decl,info,bef)::(k s)
+ | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
+ mcode starter @ r.V0.combiner_statement_dots stmt_dots @ mcode ender
+ | Ast0.Dots(d,whencode) | Ast0.Circles(d,whencode)
+ | Ast0.Stars(d,whencode) -> mcode d (* ignore whencode *)
+ | Ast0.OptStm s | Ast0.UniqueStm s ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_statement s
+ | _ -> do_nothing r k s in
+
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ mcode starter @
+ r.V0.combiner_expression_dots expr_dots @ mcode ender
+ | Ast0.Edots(d,whencode) | Ast0.Ecircles(d,whencode)
+ | Ast0.Estars(d,whencode) -> mcode d (* ignore whencode *)
+ | Ast0.OptExp e | Ast0.UniqueExp e ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_expression e
+ | _ -> do_nothing r k e in
+
+ let ident r k e =
+ match Ast0.unwrap e with
+ Ast0.OptIdent i | Ast0.UniqueIdent i ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_ident i
+ | _ -> do_nothing r k e in
+
+ let typeC r k e =
+ match Ast0.unwrap e with
+ Ast0.OptType t | Ast0.UniqueType t ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_typeC t
+ | _ -> do_nothing r k e in
+
+ let decl r k e =
+ match Ast0.unwrap e with
+ Ast0.OptDecl d | Ast0.UniqueDecl d ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_declaration d
+ | _ -> do_nothing r k e in
+
+ let initialiser r k e =
+ match Ast0.unwrap e with
+ Ast0.Idots(d,whencode) -> mcode d (* ignore whencode *)
+ | Ast0.OptIni i | Ast0.UniqueIni i ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_initialiser i
+ | _ -> do_nothing r k e in
+
+ let param r k e =
+ match Ast0.unwrap e with
+ Ast0.OptParam p | Ast0.UniqueParam p ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_parameter p
+ | _ -> do_nothing r k e in
+
+ let case_line r k e =
+ match Ast0.unwrap e with
+ Ast0.OptCase c ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_case_line c
+ | _ -> do_nothing r k e in
+
+ let do_top r k (e: Ast0.top_level) = k e in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ edots idots pdots sdots ddots cdots
+ ident expression typeC initialiser param decl statement case_line do_top
+
+
+let call_collect_minus context_nodes :
+ (int * (minus_join_point * Ast0.info * Ast0.mcodekind) list) list =
+ List.map
+ (function e ->
+ match e with
+ Ast0.DotsExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_expression_dots e)
+ | Ast0.DotsInitTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_initialiser_list e)
+ | Ast0.DotsParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_parameter_list e)
+ | Ast0.DotsStmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_statement_dots e)
+ | Ast0.DotsDeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_declaration_dots e)
+ | Ast0.DotsCaseTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_case_line_dots e)
+ | Ast0.IdentTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_ident e)
+ | Ast0.ExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_expression e)
+ | Ast0.ArgExprTag(e) | Ast0.TestExprTag(e) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_typeC e)
+ | Ast0.ParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_parameter e)
+ | Ast0.InitTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_initialiser e)
+ | Ast0.DeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_declaration e)
+ | Ast0.StmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_statement e)
+ | Ast0.CaseLineTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_case_line e)
+ | Ast0.TopTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_top_level e)
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
+ context_nodes
+
+(* result of collecting the join points should be sorted in nondecreasing
+ order by line *)
+let verify l =
+ let get_info = function
+ (Favored,info,_) | (Unfavored,info,_) | (Toplevel,info,_)
+ | (Decl,info,_) -> info in
+ let token_start_line x = (get_info x).Ast0.logical_start in
+ let token_end_line x = (get_info x).Ast0.logical_end in
+ let token_real_start_line x = (get_info x).Ast0.line_start in
+ let token_real_end_line x = (get_info x).Ast0.line_end in
+ List.iter
+ (function
+ (index,((_::_) as l1)) ->
+ let _ =
+ List.fold_left
+ (function (prev,real_prev) ->
+ function cur ->
+ let ln = token_start_line cur in
+ if ln < prev
+ then
+ failwith
+ (Printf.sprintf
+ "error in collection of - tokens %d less than %d"
+ (token_real_start_line cur) real_prev);
+ (token_end_line cur,token_real_end_line cur))
+ (token_end_line (List.hd l1), token_real_end_line (List.hd l1))
+ (List.tl l1) in
+ ()
+ | _ -> ()) (* dots, in eg f() has no join points *)
+ l
+
+let process_minus minus =
+ create_root_token_table minus;
+ List.concat
+ (List.map
+ (function x ->
+ let res = call_collect_minus (collect_context x) in
+ verify res;
+ res)
+ minus)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* collect the plus tokens *)
+
+let mk_baseType x = Ast.BaseTypeTag x
+let mk_structUnion x = Ast.StructUnionTag x
+let mk_sign x = Ast.SignTag x
+let mk_ident x = Ast.IdentTag (Ast0toast.ident x)
+let mk_expression x = Ast.ExpressionTag (Ast0toast.expression x)
+let mk_constant x = Ast.ConstantTag x
+let mk_unaryOp x = Ast.UnaryOpTag x
+let mk_assignOp x = Ast.AssignOpTag x
+let mk_fixOp x = Ast.FixOpTag x
+let mk_binaryOp x = Ast.BinaryOpTag x
+let mk_arithOp x = Ast.ArithOpTag x
+let mk_logicalOp x = Ast.LogicalOpTag x
+let mk_declaration x = Ast.DeclarationTag (Ast0toast.declaration x)
+let mk_topdeclaration x = Ast.DeclarationTag (Ast0toast.declaration x)
+let mk_storage x = Ast.StorageTag x
+let mk_inc_file x = Ast.IncFileTag x
+let mk_statement x = Ast.StatementTag (Ast0toast.statement x)
+let mk_case_line x = Ast.CaseLineTag (Ast0toast.case_line x)
+let mk_const_vol x = Ast.ConstVolTag x
+let mk_token x info = Ast.Token (x,Some info)
+let mk_meta (_,x) info = Ast.Token (x,Some info)
+let mk_code x = Ast.Code (Ast0toast.top_level x)
+
+let mk_exprdots x = Ast.ExprDotsTag (Ast0toast.expression_dots x)
+let mk_paramdots x = Ast.ParamDotsTag (Ast0toast.parameter_list x)
+let mk_stmtdots x = Ast.StmtDotsTag (Ast0toast.statement_dots x)
+let mk_decldots x = Ast.DeclDotsTag (Ast0toast.declaration_dots x)
+let mk_casedots x = failwith "+ case lines not supported"
+let mk_typeC x = Ast.FullTypeTag (Ast0toast.typeC x)
+let mk_init x = Ast.InitTag (Ast0toast.initialiser x)
+let mk_param x = Ast.ParamTag (Ast0toast.parameterTypeDef x)
+
+let collect_plus_nodes root =
+ let root_index = Ast0.get_index root in
+
+ let bind x y = x @ y in
+ let option_default = [] in
+
+ let mcode fn (term,_,info,mcodekind,_) =
+ match mcodekind with Ast0.PLUS -> [(info,fn term)] | _ -> [] in
+
+ let imcode fn (term,_,info,mcodekind,_) =
+ match mcodekind with
+ Ast0.PLUS -> [(info,fn term (Ast0toast.convert_info info))]
+ | _ -> [] in
+
+ let do_nothing fn r k e =
+ match Ast0.get_mcodekind e with
+ (Ast0.CONTEXT(_)) when not(Ast0.get_index e = root_index) -> []
+ | Ast0.PLUS -> [(Ast0.get_info e,fn e)]
+ | _ -> k e in
+
+ (* case for everything that is just a wrapper for a simpler thing *)
+ let stmt r k e =
+ match Ast0.unwrap e with
+ Ast0.Exp(exp) -> r.V0.combiner_expression exp
+ | Ast0.TopExp(exp) -> r.V0.combiner_expression exp
+ | Ast0.Ty(ty) -> r.V0.combiner_typeC ty
+ | Ast0.Decl(_,decl) -> r.V0.combiner_declaration decl
+ | _ -> do_nothing mk_statement r k e in
+
+ (* statementTag is preferred, because it indicates that one statement is
+ replaced by one statement, in single_statement *)
+ let stmt_dots r k e =
+ match Ast0.unwrap e with
+ Ast0.DOTS([s]) | Ast0.CIRCLES([s]) | Ast0.STARS([s]) ->
+ r.V0.combiner_statement s
+ | _ -> do_nothing mk_stmtdots r k e in
+
+ let toplevel r k e =
+ match Ast0.unwrap e with
+ Ast0.DECL(s) -> r.V0.combiner_statement s
+ | Ast0.CODE(sdots) -> r.V0.combiner_statement_dots sdots
+ | _ -> do_nothing mk_code r k e in
+
+ let initdots r k e = k e in
+
+ V0.combiner bind option_default
+ (imcode mk_meta) (imcode mk_token) (mcode mk_constant) (mcode mk_assignOp)
+ (mcode mk_fixOp)
+ (mcode mk_unaryOp) (mcode mk_binaryOp) (mcode mk_const_vol)
+ (mcode mk_baseType) (mcode mk_sign) (mcode mk_structUnion)
+ (mcode mk_storage) (mcode mk_inc_file)
+ (do_nothing mk_exprdots) initdots
+ (do_nothing mk_paramdots) stmt_dots (do_nothing mk_decldots)
+ (do_nothing mk_casedots)
+ (do_nothing mk_ident) (do_nothing mk_expression)
+ (do_nothing mk_typeC) (do_nothing mk_init) (do_nothing mk_param)
+ (do_nothing mk_declaration)
+ stmt (do_nothing mk_case_line) toplevel
+
+let call_collect_plus context_nodes :
+ (int * (Ast0.info * Ast.anything) list) list =
+ List.map
+ (function e ->
+ match e with
+ Ast0.DotsExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_expression_dots e)
+ | Ast0.DotsInitTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_initialiser_list e)
+ | Ast0.DotsParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_parameter_list e)
+ | Ast0.DotsStmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_statement_dots e)
+ | Ast0.DotsDeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_declaration_dots e)
+ | Ast0.DotsCaseTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_case_line_dots e)
+ | Ast0.IdentTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_ident e)
+ | Ast0.ExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_expression e)
+ | Ast0.ArgExprTag(_) | Ast0.TestExprTag(_) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_typeC e)
+ | Ast0.InitTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_initialiser e)
+ | Ast0.ParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_parameter e)
+ | Ast0.DeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_declaration e)
+ | Ast0.StmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_statement e)
+ | Ast0.CaseLineTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_case_line e)
+ | Ast0.TopTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_top_level e)
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
+ context_nodes
+
+(* The plus fragments are converted to a list of lists of lists.
+Innermost list: Elements have type anything. For any pair of successive
+elements, n and n+1, the ending line of n is the same as the starting line
+of n+1.
+Middle lists: For any pair of successive elements, n and n+1, the ending
+line of n is one less than the starting line of n+1.
+Outer list: For any pair of successive elements, n and n+1, the ending
+line of n is more than one less than the starting line of n+1. *)
+
+let logstart info = info.Ast0.logical_start
+let logend info = info.Ast0.logical_end
+
+let redo info start finish =
+ {{info with Ast0.logical_start = start} with Ast0.logical_end = finish}
+
+let rec find_neighbors (index,l) :
+ int * (Ast0.info * (Ast.anything list list)) list =
+ let rec loop = function
+ [] -> []
+ | (i,x)::rest ->
+ (match loop rest with
+ ((i1,(x1::rest_inner))::rest_middle)::rest_outer ->
+ let finish1 = logend i in
+ let start2 = logstart i1 in
+ if finish1 = start2
+ then
+ ((redo i (logstart i) (logend i1),(x::x1::rest_inner))
+ ::rest_middle)
+ ::rest_outer
+ else if finish1 + 1 = start2
+ then ((i,[x])::(i1,(x1::rest_inner))::rest_middle)::rest_outer
+ else [(i,[x])]::((i1,(x1::rest_inner))::rest_middle)::rest_outer
+ | _ -> [[(i,[x])]]) (* rest must be [] *) in
+ let res =
+ List.map
+ (function l ->
+ let (start_info,_) = List.hd l in
+ let (end_info,_) = List.hd (List.rev l) in
+ (redo start_info (logstart start_info) (logend end_info),
+ List.map (function (_,x) -> x) l))
+ (loop l) in
+ (index,res)
+
+let process_plus plus :
+ (int * (Ast0.info * Ast.anything list list) list) list =
+ List.concat
+ (List.map
+ (function x ->
+ List.map find_neighbors (call_collect_plus (collect_context x)))
+ plus)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* merge *)
+(*
+let merge_one = function
+ (m1::m2::minus_info,p::plus_info) ->
+ if p < m1, then
+ attach p to the beginning of m1.bef if m1 is Good, fail if it is bad
+ if p > m1 && p < m2, then consider the following possibilities, in order
+ m1 is Good and favored: attach to the beginning of m1.aft
+ m2 is Good and favored: attach to the beginning of m2.bef; drop m1
+ m1 is Good and unfavored: attach to the beginning of m1.aft
+ m2 is Good and unfavored: attach to the beginning of m2.bef; drop m1
+ also flip m1.bef if the first where > m1
+ if we drop m1, then flip m1.aft first
+ if p > m2
+ m2 is Good and favored: attach to the beginning of m2.aft; drop m1
+*)
+
+(* end of first argument < start/end of second argument *)
+let less_than_start info1 info2 =
+ info1.Ast0.logical_end < info2.Ast0.logical_start
+let less_than_end info1 info2 =
+ info1.Ast0.logical_end < info2.Ast0.logical_end
+let greater_than_end info1 info2 =
+ info1.Ast0.logical_start > info2.Ast0.logical_end
+let good_start info = info.Ast0.attachable_start
+let good_end info = info.Ast0.attachable_end
+
+let toplevel = function Toplevel -> true | Favored | Unfavored | Decl -> false
+let decl = function Decl -> true | Favored | Unfavored | Toplevel -> false
+let favored = function Favored -> true | Unfavored | Toplevel | Decl -> false
+
+let top_code =
+ List.for_all (List.for_all (function Ast.Code _ -> true | _ -> false))
+
+(* The following is probably not correct. The idea is to detect what
+should be placed completely before the declaration. So type/storage
+related things do not fall into this category, and complete statements do
+fall into this category. But perhaps other things should be in this
+category as well, such as { or ;? *)
+let predecl_code =
+ let tester = function
+ (* the following should definitely be true *)
+ Ast.DeclarationTag _
+ | Ast.StatementTag _
+ | Ast.Rule_elemTag _
+ | Ast.StmtDotsTag _
+ | Ast.Code _ -> true
+ (* the following should definitely be false *)
+ | Ast.FullTypeTag _ | Ast.BaseTypeTag _ | Ast.StructUnionTag _
+ | Ast.SignTag _
+ | Ast.StorageTag _ | Ast.ConstVolTag _ | Ast.TypeCTag _ -> false
+ (* not sure about the rest *)
+ | _ -> false in
+ List.for_all (List.for_all tester)
+
+let pr = Printf.sprintf
+
+let insert thing thinginfo into intoinfo =
+ let get_last l = let l = List.rev l in (List.rev(List.tl l),List.hd l) in
+ let get_first l = (List.hd l,List.tl l) in
+ let thing_start = thinginfo.Ast0.logical_start in
+ let thing_end = thinginfo.Ast0.logical_end in
+ let thing_offset = thinginfo.Ast0.offset in
+ let into_start = intoinfo.Ast0.tline_start in
+ let into_end = intoinfo.Ast0.tline_end in
+ let into_left_offset = intoinfo.Ast0.left_offset in
+ let into_right_offset = intoinfo.Ast0.right_offset in
+ Printf.printf "thing start %d thing end %d into start %d into end %d\n"
+ thing_start thing_end into_start into_end;
+ if thing_end < into_start && thing_start < into_start
+ then (thing@into,
+ {{intoinfo with Ast0.tline_start = thing_start}
+ with Ast0.left_offset = thing_offset})
+ else if thing_end = into_start && thing_offset < into_left_offset
+ then
+ let (prev,last) = get_last thing in
+ let (first,rest) = get_first into in
+ (prev@[last@first]@rest,
+ {{intoinfo with Ast0.tline_start = thing_start}
+ with Ast0.left_offset = thing_offset})
+ else if thing_start > into_end && thing_end > into_end
+ then (into@thing,
+ {{intoinfo with Ast0.tline_end = thing_end}
+ with Ast0.right_offset = thing_offset})
+ else if thing_start = into_end && thing_offset > into_right_offset
+ then
+ let (first,rest) = get_first thing in
+ let (prev,last) = get_last into in
+ (prev@[last@first]@rest,
+ {{intoinfo with Ast0.tline_end = thing_end}
+ with Ast0.right_offset = thing_offset})
+ else
+ begin
+ Printf.printf "thing start %d thing end %d into start %d into end %d\n"
+ thing_start thing_end into_start into_end;
+ Printf.printf "thing offset %d left offset %d right offset %d\n"
+ thing_offset into_left_offset into_right_offset;
+ Pretty_print_cocci.print_anything "" thing;
+ failwith "can't figure out where to put the + code"
+ end
+
+let init thing info =
+ (thing,
+ {Ast0.tline_start = info.Ast0.logical_start;
+ Ast0.tline_end = info.Ast0.logical_end;
+ Ast0.left_offset = info.Ast0.offset;
+ Ast0.right_offset = info.Ast0.offset})
+
+let attachbefore (infop,p) = function
+ Ast0.MINUS(replacements) ->
+ (match !replacements with
+ ([],ti) -> replacements := init p infop
+ | (repl,ti) -> replacements := insert p infop repl ti)
+ | Ast0.CONTEXT(neighbors) ->
+ let (repl,ti1,ti2) = !neighbors in
+ (match repl with
+ Ast.BEFORE(bef) ->
+ let (bef,ti1) = insert p infop bef ti1 in
+ neighbors := (Ast.BEFORE(bef),ti1,ti2)
+ | Ast.AFTER(aft) ->
+ let (bef,ti1) = init p infop in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.BEFOREAFTER(bef,aft) ->
+ let (bef,ti1) = insert p infop bef ti1 in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.NOTHING ->
+ let (bef,ti1) = init p infop in
+ neighbors := (Ast.BEFORE(bef),ti1,ti2))
+ | _ -> failwith "not possible for attachbefore"
+
+let attachafter (infop,p) = function
+ Ast0.MINUS(replacements) ->
+ (match !replacements with
+ ([],ti) -> replacements := init p infop
+ | (repl,ti) -> replacements := insert p infop repl ti)
+ | Ast0.CONTEXT(neighbors) ->
+ let (repl,ti1,ti2) = !neighbors in
+ (match repl with
+ Ast.BEFORE(bef) ->
+ let (aft,ti2) = init p infop in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.AFTER(aft) ->
+ let (aft,ti2) = insert p infop aft ti2 in
+ neighbors := (Ast.AFTER(aft),ti1,ti2)
+ | Ast.BEFOREAFTER(bef,aft) ->
+ let (aft,ti2) = insert p infop aft ti2 in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.NOTHING ->
+ let (aft,ti2) = init p infop in
+ neighbors := (Ast.AFTER(aft),ti1,ti2))
+ | _ -> failwith "not possible for attachbefore"
+
+let attach_all_before ps m =
+ List.iter (function x -> attachbefore x m) ps
+
+let attach_all_after ps m =
+ List.iter (function x -> attachafter x m) ps
+
+let split_at_end info ps =
+ let split_point = info.Ast0.logical_end in
+ List.partition
+ (function (info,_) -> info.Ast0.logical_end < split_point)
+ ps
+
+let allminus = function
+ Ast0.MINUS(_) -> true
+ | _ -> false
+
+let rec before_m1 ((f1,infom1,m1) as x1) ((f2,infom2,m2) as x2) rest = function
+ [] -> ()
+ | (((infop,_) as p) :: ps) as all ->
+ if less_than_start infop infom1 or
+ (allminus m1 && less_than_end infop infom1) (* account for trees *)
+ then
+ if good_start infom1
+ then (attachbefore p m1; before_m1 x1 x2 rest ps)
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ else after_m1 x1 x2 rest all
+
+and after_m1 ((f1,infom1,m1) as x1) ((f2,infom2,m2) as x2) rest = function
+ [] -> ()
+ | (((infop,pcode) as p) :: ps) as all ->
+ (* if the following is false, then some + code is stuck in the middle
+ of some context code (m1). could drop down to the token level.
+ this might require adjustments in ast0toast as well, when + code on
+ expressions is dropped down to + code on expressions. it might
+ also break some invariants on which iso depends, particularly on
+ what it can infer from something being CONTEXT with no top-level
+ modifications. for the moment, we thus give an error, asking the
+ user to rewrite the semantic patch. *)
+ if greater_than_end infop infom1
+ then
+ if less_than_start infop infom2
+ then
+ if predecl_code pcode && good_end infom1 && decl f1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if predecl_code pcode && good_start infom2 && decl f2
+ then before_m2 x2 rest all
+ else if top_code pcode && good_end infom1 && toplevel f1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if top_code pcode && good_start infom2 && toplevel f2
+ then before_m2 x2 rest all
+ else if good_end infom1 && favored f1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if good_start infom2 && favored f2
+ then before_m2 x2 rest all
+ else if good_end infom1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if good_start infom2
+ then before_m2 x2 rest all
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ else after_m2 x2 rest all
+ else
+ begin
+ Printf.printf "between: p start %d p end %d m1 start %d m1 end %d m2 start %d m2 end %d\n"
+ infop.Ast0.line_start infop.Ast0.line_end
+ infom1.Ast0.line_start infom1.Ast0.line_end
+ infom2.Ast0.line_start infom2.Ast0.line_end;
+ Pretty_print_cocci.print_anything "" pcode;
+ failwith
+ "The semantic patch is structured in a way that may give bad results with isomorphisms. Please try to rewrite it by moving + code out from -/context terms."
+ end
+
+and before_m2 ((f2,infom2,m2) as x2) rest
+ (p : (Ast0.info * Ast.anything list list) list) =
+ match (rest,p) with
+ (_,[]) -> ()
+ | ([],((infop,_)::_)) ->
+ let (bef_m2,aft_m2) = split_at_end infom2 p in (* bef_m2 isn't empty *)
+ if good_start infom2
+ then (attach_all_before bef_m2 m2; after_m2 x2 rest aft_m2)
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ | (m::ms,_) -> before_m1 x2 m ms p
+
+and after_m2 ((f2,infom2,m2) as x2) rest
+ (p : (Ast0.info * Ast.anything list list) list) =
+ match (rest,p) with
+ (_,[]) -> ()
+ | ([],((infop,_)::_)) ->
+ if good_end infom2
+ then attach_all_after p m2
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ | (m::ms,_) -> after_m1 x2 m ms p
+
+let merge_one : (minus_join_point * Ast0.info * 'a) list *
+ (Ast0.info * Ast.anything list list) list -> unit = function (m,p) ->
+ (*
+ Printf.printf "minus code\n";
+ List.iter
+ (function (_,info,_) ->
+ Printf.printf "start %d end %d real_start %d real_end %d\n"
+ info.Ast0.logical_start info.Ast0.logical_end
+ info.Ast0.line_start info.Ast0.line_end)
+ m;
+ Printf.printf "plus code\n";
+ List.iter
+ (function (info,p) ->
+ Printf.printf "start %d end %d real_start %d real_end %d\n"
+ info.Ast0.logical_start info.Ast0.logical_end
+ info.Ast0.line_end info.Ast0.line_end;
+ Pretty_print_cocci.print_anything "" p;
+ Format.print_newline())
+ p;
+ *)
+ match (m,p) with
+ (_,[]) -> ()
+ | (m1::m2::restm,p) -> before_m1 m1 m2 restm p
+ | ([m],p) -> before_m2 m [] p
+ | ([],_) -> failwith "minus tree ran out before the plus tree"
+
+let merge minus_list plus_list =
+ (*
+ Printf.printf "minus list %s\n"
+ (String.concat " "
+ (List.map (function (x,_) -> string_of_int x) minus_list));
+ Printf.printf "plus list %s\n"
+ (String.concat " "
+ (List.map (function (x,_) -> string_of_int x) plus_list));
+ *)
+ List.iter
+ (function (index,minus_info) ->
+ let plus_info = List.assoc index plus_list in
+ merge_one (minus_info,plus_info))
+ minus_list
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Need to check that CONTEXT nodes have nothing attached to their tokens.
+If they do, they become MIXED *)
+
+let reevaluate_contextness =
+ let bind = (@) in
+ let option_default = [] in
+
+ let mcode (_,_,_,mc,_) =
+ match mc with
+ Ast0.CONTEXT(mc) -> let (ba,_,_) = !mc in [ba]
+ | _ -> [] in
+
+ let donothing r k e =
+ match Ast0.get_mcodekind e with
+ Ast0.CONTEXT(mc) ->
+ if List.exists (function Ast.NOTHING -> false | _ -> true) (k e)
+ then Ast0.set_mcodekind e (Ast0.MIXED(mc));
+ []
+ | _ -> let _ = k e in [] in
+
+ let res =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing
+ donothing donothing donothing donothing donothing donothing donothing in
+ res.V0.combiner_top_level
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+
+let insert_plus minus plus =
+ let minus_stream = process_minus minus in
+ let plus_stream = process_plus plus in
+ merge minus_stream plus_stream;
+ List.iter (function x -> let _ = reevaluate_contextness x in ()) minus
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* The error message "no available token to attach to" often comes in an
+argument list of unbounded length. In this case, one should move a comma so
+that there is a comma after the + code. *)
+
+(* Start at all of the corresponding BindContext nodes in the minus and
+plus trees, and traverse their children. We take the same strategy as
+before: collect the list of minus/context nodes/tokens and the list of plus
+tokens, and then merge them. *)
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+module CN = Context_neg
+
+let get_option f = function
+ None -> []
+ | Some x -> f x
+
+(* --------------------------------------------------------------------- *)
+(* Collect root and all context nodes in a tree *)
+
+let collect_context e =
+ let bind x y = x @ y in
+ let option_default = [] in
+
+ let mcode _ = [] in
+
+ let donothing builder r k e =
+ match Ast0.get_mcodekind e with
+ Ast0.CONTEXT(_) -> (builder e) :: (k e)
+ | _ -> k e in
+
+(* special case for everything that contains whencode, so that we skip over
+it *)
+ let expression r k e =
+ donothing Ast0.expr r k
+ (Ast0.rewrap e
+ (match Ast0.unwrap e with
+ Ast0.NestExpr(starter,exp,ender,whencode,multi) ->
+ Ast0.NestExpr(starter,exp,ender,None,multi)
+ | Ast0.Edots(dots,whencode) -> Ast0.Edots(dots,None)
+ | Ast0.Ecircles(dots,whencode) -> Ast0.Ecircles(dots,None)
+ | Ast0.Estars(dots,whencode) -> Ast0.Estars(dots,None)
+ | e -> e)) in
+
+ let initialiser r k i =
+ donothing Ast0.ini r k
+ (Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.Idots(dots,whencode) -> Ast0.Idots(dots,None)
+ | i -> i)) in
+
+ let statement r k s =
+ donothing Ast0.stmt r k
+ (Ast0.rewrap s
+ (match Ast0.unwrap s with
+ Ast0.Nest(started,stm_dots,ender,whencode,multi) ->
+ Ast0.Nest(started,stm_dots,ender,[],multi)
+ | Ast0.Dots(dots,whencode) -> Ast0.Dots(dots,[])
+ | Ast0.Circles(dots,whencode) -> Ast0.Circles(dots,[])
+ | Ast0.Stars(dots,whencode) -> Ast0.Stars(dots,[])
+ | s -> s)) in
+
+ let topfn r k e = Ast0.TopTag(e) :: (k e) in
+
+ let res =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ (donothing Ast0.dotsExpr) (donothing Ast0.dotsInit)
+ (donothing Ast0.dotsParam) (donothing Ast0.dotsStmt)
+ (donothing Ast0.dotsDecl) (donothing Ast0.dotsCase)
+ (donothing Ast0.ident) expression (donothing Ast0.typeC) initialiser
+ (donothing Ast0.param) (donothing Ast0.decl) statement
+ (donothing Ast0.case_line) topfn in
+ res.V0.combiner_top_level e
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* collect the possible join points, in order, among the children of a
+BindContext. Dots are not allowed. Nests and disjunctions are no problem,
+because their delimiters take up a line by themselves *)
+
+(* An Unfavored token is one that is in a BindContext node; using this causes
+ the node to become Neither, meaning that isomorphisms can't be applied *)
+(* Toplevel is for the bef token of a function declaration and is for
+attaching top-level definitions that should come before the complete
+declaration *)
+type minus_join_point = Favored | Unfavored | Toplevel | Decl
+
+(* Maps the index of a node to the indices of the mcodes it contains *)
+let root_token_table = (Hashtbl.create(50) : (int, int list) Hashtbl.t)
+
+let create_root_token_table minus =
+ Hashtbl.iter
+ (function tokens ->
+ function (node,_) ->
+ let key =
+ match node with
+ Ast0.DotsExprTag(d) -> Ast0.get_index d
+ | Ast0.DotsInitTag(d) -> Ast0.get_index d
+ | Ast0.DotsParamTag(d) -> Ast0.get_index d
+ | Ast0.DotsStmtTag(d) -> Ast0.get_index d
+ | Ast0.DotsDeclTag(d) -> Ast0.get_index d
+ | Ast0.DotsCaseTag(d) -> Ast0.get_index d
+ | Ast0.IdentTag(d) -> Ast0.get_index d
+ | Ast0.ExprTag(d) -> Ast0.get_index d
+ | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(d) -> Ast0.get_index d
+ | Ast0.ParamTag(d) -> Ast0.get_index d
+ | Ast0.InitTag(d) -> Ast0.get_index d
+ | Ast0.DeclTag(d) -> Ast0.get_index d
+ | Ast0.StmtTag(d) -> Ast0.get_index d
+ | Ast0.CaseLineTag(d) -> Ast0.get_index d
+ | Ast0.TopTag(d) -> Ast0.get_index d
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+ in
+ Hashtbl.add root_token_table key tokens)
+ CN.minus_table;
+ List.iter
+ (function r ->
+ let index = Ast0.get_index r in
+ try let _ = Hashtbl.find root_token_table index in ()
+ with Not_found -> Hashtbl.add root_token_table index [])
+ minus
+
+let collect_minus_join_points root =
+ let root_index = Ast0.get_index root in
+ let unfavored_tokens = Hashtbl.find root_token_table root_index in
+ let bind x y = x @ y in
+ let option_default = [] in
+
+ let mcode (_,_,info,mcodekind,_) =
+ if List.mem (info.Ast0.offset) unfavored_tokens
+ then [(Unfavored,info,mcodekind)]
+ else [(Favored,info,mcodekind)] in
+
+ let do_nothing r k e =
+ let info = Ast0.get_info e in
+ let index = Ast0.get_index e in
+ match Ast0.get_mcodekind e with
+ (Ast0.MINUS(_)) as mc -> [(Favored,info,mc)]
+ | (Ast0.CONTEXT(_)) as mc when not(index = root_index) ->
+ (* This was unfavored at one point, but I don't remember why *)
+ [(Favored,info,mc)]
+ | _ -> k e in
+
+(* don't want to attach to the outside of DOTS, because metavariables can't
+bind to that; not good for isomorphisms *)
+
+ let dots f k d =
+ let multibind l =
+ let rec loop = function
+ [] -> option_default
+ | [x] -> x
+ | x::xs -> bind x (loop xs) in
+ loop l in
+
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> multibind (List.map f l)
+ | Ast0.CIRCLES(l) -> multibind (List.map f l)
+ | Ast0.STARS(l) -> multibind (List.map f l) in
+
+ let edots r k d = dots r.V0.combiner_expression k d in
+ let idots r k d = dots r.V0.combiner_initialiser k d in
+ let pdots r k d = dots r.V0.combiner_parameter k d in
+ let sdots r k d = dots r.V0.combiner_statement k d in
+ let ddots r k d = dots r.V0.combiner_declaration k d in
+ let cdots r k d = dots r.V0.combiner_case_line k d in
+
+ (* a case for everything that has a Opt *)
+
+ let statement r k s =
+ (*
+ let redo_branched res (ifinfo,aftmc) =
+ let redo fv info mc rest =
+ let new_info = {info with Ast0.attachable_end = false} in
+ List.rev ((Favored,ifinfo,aftmc)::(fv,new_info,mc)::rest) in
+ match List.rev res with
+ [(fv,info,mc)] ->
+ (match mc with
+ Ast0.MINUS(_) | Ast0.CONTEXT(_) ->
+ (* even for -, better for isos not to integrate code after an
+ if into the if body.
+ but the problem is that this can extend the region in
+ which a variable is bound, because a variable bound in the
+ aft node would seem to have to be live in the whole if,
+ whereas we might like it to be live in only one branch.
+ ie ideally, if we can keep the minus code in the right
+ order, we would like to drop it as close to the bindings
+ of its free variables. This could be anywhere in the minus
+ code. Perhaps we would like to do this after the
+ application of isomorphisms, though.
+ *)
+ redo fv info mc []
+ | _ -> res)
+ | (fv,info,mc)::rest ->
+ (match mc with
+ Ast0.CONTEXT(_) -> redo fv info mc rest
+ | _ -> res)
+ | _ -> failwith "unexpected empty code" in *)
+ match Ast0.unwrap s with
+ (* Ast0.IfThen(_,_,_,_,_,aft)
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,aft)
+ | Ast0.While(_,_,_,_,_,aft)
+ | Ast0.For(_,_,_,_,_,_,_,_,_,aft)
+ | Ast0.Iterator(_,_,_,_,_,aft) ->
+ redo_branched (do_nothing r k s) aft*)
+ | Ast0.FunDecl((info,bef),fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ (Toplevel,info,bef)::(k s)
+ | Ast0.Decl((info,bef),decl) -> (Decl,info,bef)::(k s)
+ | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
+ mcode starter @ r.V0.combiner_statement_dots stmt_dots @ mcode ender
+ | Ast0.Dots(d,whencode) | Ast0.Circles(d,whencode)
+ | Ast0.Stars(d,whencode) -> mcode d (* ignore whencode *)
+ | Ast0.OptStm s | Ast0.UniqueStm s ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_statement s
+ | _ -> do_nothing r k s in
+
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ mcode starter @
+ r.V0.combiner_expression_dots expr_dots @ mcode ender
+ | Ast0.Edots(d,whencode) | Ast0.Ecircles(d,whencode)
+ | Ast0.Estars(d,whencode) -> mcode d (* ignore whencode *)
+ | Ast0.OptExp e | Ast0.UniqueExp e ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_expression e
+ | _ -> do_nothing r k e in
+
+ let ident r k e =
+ match Ast0.unwrap e with
+ Ast0.OptIdent i | Ast0.UniqueIdent i ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_ident i
+ | _ -> do_nothing r k e in
+
+ let typeC r k e =
+ match Ast0.unwrap e with
+ Ast0.OptType t | Ast0.UniqueType t ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_typeC t
+ | _ -> do_nothing r k e in
+
+ let decl r k e =
+ match Ast0.unwrap e with
+ Ast0.OptDecl d | Ast0.UniqueDecl d ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_declaration d
+ | _ -> do_nothing r k e in
+
+ let initialiser r k e =
+ match Ast0.unwrap e with
+ Ast0.Idots(d,whencode) -> mcode d (* ignore whencode *)
+ | Ast0.OptIni i | Ast0.UniqueIni i ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_initialiser i
+ | _ -> do_nothing r k e in
+
+ let param r k e =
+ match Ast0.unwrap e with
+ Ast0.OptParam p | Ast0.UniqueParam p ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_parameter p
+ | _ -> do_nothing r k e in
+
+ let case_line r k e =
+ match Ast0.unwrap e with
+ Ast0.OptCase c ->
+ (* put the + code on the thing, not on the opt *)
+ r.V0.combiner_case_line c
+ | _ -> do_nothing r k e in
+
+ let do_top r k (e: Ast0.top_level) = k e in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ edots idots pdots sdots ddots cdots
+ ident expression typeC initialiser param decl statement case_line do_top
+
+
+let call_collect_minus context_nodes :
+ (int * (minus_join_point * Ast0.info * Ast0.mcodekind) list) list =
+ List.map
+ (function e ->
+ match e with
+ Ast0.DotsExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_expression_dots e)
+ | Ast0.DotsInitTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_initialiser_list e)
+ | Ast0.DotsParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_parameter_list e)
+ | Ast0.DotsStmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_statement_dots e)
+ | Ast0.DotsDeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_declaration_dots e)
+ | Ast0.DotsCaseTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_case_line_dots e)
+ | Ast0.IdentTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_ident e)
+ | Ast0.ExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_expression e)
+ | Ast0.ArgExprTag(e) | Ast0.TestExprTag(e) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_typeC e)
+ | Ast0.ParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_parameter e)
+ | Ast0.InitTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_initialiser e)
+ | Ast0.DeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_declaration e)
+ | Ast0.StmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_statement e)
+ | Ast0.CaseLineTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_case_line e)
+ | Ast0.TopTag(e) ->
+ (Ast0.get_index e,
+ (collect_minus_join_points e).V0.combiner_top_level e)
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
+ context_nodes
+
+(* result of collecting the join points should be sorted in nondecreasing
+ order by line *)
+let verify l =
+ let get_info = function
+ (Favored,info,_) | (Unfavored,info,_) | (Toplevel,info,_)
+ | (Decl,info,_) -> info in
+ let token_start_line x = (get_info x).Ast0.logical_start in
+ let token_end_line x = (get_info x).Ast0.logical_end in
+ let token_real_start_line x = (get_info x).Ast0.line_start in
+ let token_real_end_line x = (get_info x).Ast0.line_end in
+ List.iter
+ (function
+ (index,((_::_) as l1)) ->
+ let _ =
+ List.fold_left
+ (function (prev,real_prev) ->
+ function cur ->
+ let ln = token_start_line cur in
+ if ln < prev
+ then
+ failwith
+ (Printf.sprintf
+ "error in collection of - tokens %d less than %d"
+ (token_real_start_line cur) real_prev);
+ (token_end_line cur,token_real_end_line cur))
+ (token_end_line (List.hd l1), token_real_end_line (List.hd l1))
+ (List.tl l1) in
+ ()
+ | _ -> ()) (* dots, in eg f() has no join points *)
+ l
+
+let process_minus minus =
+ create_root_token_table minus;
+ List.concat
+ (List.map
+ (function x ->
+ let res = call_collect_minus (collect_context x) in
+ verify res;
+ res)
+ minus)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* collect the plus tokens *)
+
+let mk_baseType x = Ast.BaseTypeTag x
+let mk_structUnion x = Ast.StructUnionTag x
+let mk_sign x = Ast.SignTag x
+let mk_ident x = Ast.IdentTag (Ast0toast.ident x)
+let mk_expression x = Ast.ExpressionTag (Ast0toast.expression x)
+let mk_constant x = Ast.ConstantTag x
+let mk_unaryOp x = Ast.UnaryOpTag x
+let mk_assignOp x = Ast.AssignOpTag x
+let mk_fixOp x = Ast.FixOpTag x
+let mk_binaryOp x = Ast.BinaryOpTag x
+let mk_arithOp x = Ast.ArithOpTag x
+let mk_logicalOp x = Ast.LogicalOpTag x
+let mk_declaration x = Ast.DeclarationTag (Ast0toast.declaration x)
+let mk_topdeclaration x = Ast.DeclarationTag (Ast0toast.declaration x)
+let mk_storage x = Ast.StorageTag x
+let mk_inc_file x = Ast.IncFileTag x
+let mk_statement x = Ast.StatementTag (Ast0toast.statement x)
+let mk_case_line x = Ast.CaseLineTag (Ast0toast.case_line x)
+let mk_const_vol x = Ast.ConstVolTag x
+let mk_token x info = Ast.Token (x,Some info)
+let mk_meta (_,x) info = Ast.Token (x,Some info)
+let mk_code x = Ast.Code (Ast0toast.top_level x)
+
+let mk_exprdots x = Ast.ExprDotsTag (Ast0toast.expression_dots x)
+let mk_paramdots x = Ast.ParamDotsTag (Ast0toast.parameter_list x)
+let mk_stmtdots x = Ast.StmtDotsTag (Ast0toast.statement_dots x)
+let mk_decldots x = Ast.DeclDotsTag (Ast0toast.declaration_dots x)
+let mk_casedots x = failwith "+ case lines not supported"
+let mk_typeC x = Ast.FullTypeTag (Ast0toast.typeC x)
+let mk_init x = Ast.InitTag (Ast0toast.initialiser x)
+let mk_param x = Ast.ParamTag (Ast0toast.parameterTypeDef x)
+
+let collect_plus_nodes root =
+ let root_index = Ast0.get_index root in
+
+ let bind x y = x @ y in
+ let option_default = [] in
+
+ let mcode fn (term,_,info,mcodekind,_) =
+ match mcodekind with Ast0.PLUS -> [(info,fn term)] | _ -> [] in
+
+ let imcode fn (term,_,info,mcodekind,_) =
+ match mcodekind with
+ Ast0.PLUS -> [(info,fn term (Ast0toast.convert_info info))]
+ | _ -> [] in
+
+ let do_nothing fn r k e =
+ match Ast0.get_mcodekind e with
+ (Ast0.CONTEXT(_)) when not(Ast0.get_index e = root_index) -> []
+ | Ast0.PLUS -> [(Ast0.get_info e,fn e)]
+ | _ -> k e in
+
+ (* case for everything that is just a wrapper for a simpler thing *)
+ let stmt r k e =
+ match Ast0.unwrap e with
+ Ast0.Exp(exp) -> r.V0.combiner_expression exp
+ | Ast0.TopExp(exp) -> r.V0.combiner_expression exp
+ | Ast0.Ty(ty) -> r.V0.combiner_typeC ty
+ | Ast0.Decl(_,decl) -> r.V0.combiner_declaration decl
+ | _ -> do_nothing mk_statement r k e in
+
+ (* statementTag is preferred, because it indicates that one statement is
+ replaced by one statement, in single_statement *)
+ let stmt_dots r k e =
+ match Ast0.unwrap e with
+ Ast0.DOTS([s]) | Ast0.CIRCLES([s]) | Ast0.STARS([s]) ->
+ r.V0.combiner_statement s
+ | _ -> do_nothing mk_stmtdots r k e in
+
+ let toplevel r k e =
+ match Ast0.unwrap e with
+ Ast0.DECL(s) -> r.V0.combiner_statement s
+ | Ast0.CODE(sdots) -> r.V0.combiner_statement_dots sdots
+ | _ -> do_nothing mk_code r k e in
+
+ let initdots r k e = k e in
+
+ V0.combiner bind option_default
+ (imcode mk_meta) (imcode mk_token) (mcode mk_constant) (mcode mk_assignOp)
+ (mcode mk_fixOp)
+ (mcode mk_unaryOp) (mcode mk_binaryOp) (mcode mk_const_vol)
+ (mcode mk_baseType) (mcode mk_sign) (mcode mk_structUnion)
+ (mcode mk_storage) (mcode mk_inc_file)
+ (do_nothing mk_exprdots) initdots
+ (do_nothing mk_paramdots) stmt_dots (do_nothing mk_decldots)
+ (do_nothing mk_casedots)
+ (do_nothing mk_ident) (do_nothing mk_expression)
+ (do_nothing mk_typeC) (do_nothing mk_init) (do_nothing mk_param)
+ (do_nothing mk_declaration)
+ stmt (do_nothing mk_case_line) toplevel
+
+let call_collect_plus context_nodes :
+ (int * (Ast0.info * Ast.anything) list) list =
+ List.map
+ (function e ->
+ match e with
+ Ast0.DotsExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_expression_dots e)
+ | Ast0.DotsInitTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_initialiser_list e)
+ | Ast0.DotsParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_parameter_list e)
+ | Ast0.DotsStmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_statement_dots e)
+ | Ast0.DotsDeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_declaration_dots e)
+ | Ast0.DotsCaseTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_case_line_dots e)
+ | Ast0.IdentTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_ident e)
+ | Ast0.ExprTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_expression e)
+ | Ast0.ArgExprTag(_) | Ast0.TestExprTag(_) ->
+ failwith "not possible - iso only"
+ | Ast0.TypeCTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_typeC e)
+ | Ast0.InitTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_initialiser e)
+ | Ast0.ParamTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_parameter e)
+ | Ast0.DeclTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_declaration e)
+ | Ast0.StmtTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_statement e)
+ | Ast0.CaseLineTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_case_line e)
+ | Ast0.TopTag(e) ->
+ (Ast0.get_index e,
+ (collect_plus_nodes e).V0.combiner_top_level e)
+ | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
+ | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
+ context_nodes
+
+(* The plus fragments are converted to a list of lists of lists.
+Innermost list: Elements have type anything. For any pair of successive
+elements, n and n+1, the ending line of n is the same as the starting line
+of n+1.
+Middle lists: For any pair of successive elements, n and n+1, the ending
+line of n is one less than the starting line of n+1.
+Outer list: For any pair of successive elements, n and n+1, the ending
+line of n is more than one less than the starting line of n+1. *)
+
+let logstart info = info.Ast0.logical_start
+let logend info = info.Ast0.logical_end
+
+let redo info start finish =
+ {{info with Ast0.logical_start = start} with Ast0.logical_end = finish}
+
+let rec find_neighbors (index,l) :
+ int * (Ast0.info * (Ast.anything list list)) list =
+ let rec loop = function
+ [] -> []
+ | (i,x)::rest ->
+ (match loop rest with
+ ((i1,(x1::rest_inner))::rest_middle)::rest_outer ->
+ let finish1 = logend i in
+ let start2 = logstart i1 in
+ if finish1 = start2
+ then
+ ((redo i (logstart i) (logend i1),(x::x1::rest_inner))
+ ::rest_middle)
+ ::rest_outer
+ else if finish1 + 1 = start2
+ then ((i,[x])::(i1,(x1::rest_inner))::rest_middle)::rest_outer
+ else [(i,[x])]::((i1,(x1::rest_inner))::rest_middle)::rest_outer
+ | _ -> [[(i,[x])]]) (* rest must be [] *) in
+ let res =
+ List.map
+ (function l ->
+ let (start_info,_) = List.hd l in
+ let (end_info,_) = List.hd (List.rev l) in
+ (redo start_info (logstart start_info) (logend end_info),
+ List.map (function (_,x) -> x) l))
+ (loop l) in
+ (index,res)
+
+let process_plus plus :
+ (int * (Ast0.info * Ast.anything list list) list) list =
+ List.concat
+ (List.map
+ (function x ->
+ List.map find_neighbors (call_collect_plus (collect_context x)))
+ plus)
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* merge *)
+(*
+let merge_one = function
+ (m1::m2::minus_info,p::plus_info) ->
+ if p < m1, then
+ attach p to the beginning of m1.bef if m1 is Good, fail if it is bad
+ if p > m1 && p < m2, then consider the following possibilities, in order
+ m1 is Good and favored: attach to the beginning of m1.aft
+ m2 is Good and favored: attach to the beginning of m2.bef; drop m1
+ m1 is Good and unfavored: attach to the beginning of m1.aft
+ m2 is Good and unfavored: attach to the beginning of m2.bef; drop m1
+ also flip m1.bef if the first where > m1
+ if we drop m1, then flip m1.aft first
+ if p > m2
+ m2 is Good and favored: attach to the beginning of m2.aft; drop m1
+*)
+
+(* end of first argument < start/end of second argument *)
+let less_than_start info1 info2 =
+ info1.Ast0.logical_end < info2.Ast0.logical_start
+let less_than_end info1 info2 =
+ info1.Ast0.logical_end < info2.Ast0.logical_end
+let greater_than_end info1 info2 =
+ info1.Ast0.logical_start > info2.Ast0.logical_end
+let good_start info = info.Ast0.attachable_start
+let good_end info = info.Ast0.attachable_end
+
+let toplevel = function Toplevel -> true | Favored | Unfavored | Decl -> false
+let decl = function Decl -> true | Favored | Unfavored | Toplevel -> false
+let favored = function Favored -> true | Unfavored | Toplevel | Decl -> false
+
+let top_code =
+ List.for_all (List.for_all (function Ast.Code _ -> true | _ -> false))
+
+(* The following is probably not correct. The idea is to detect what
+should be placed completely before the declaration. So type/storage
+related things do not fall into this category, and complete statements do
+fall into this category. But perhaps other things should be in this
+category as well, such as { or ;? *)
+let predecl_code =
+ let tester = function
+ (* the following should definitely be true *)
+ Ast.DeclarationTag _
+ | Ast.StatementTag _
+ | Ast.Rule_elemTag _
+ | Ast.StmtDotsTag _
+ | Ast.Code _ -> true
+ (* the following should definitely be false *)
+ | Ast.FullTypeTag _ | Ast.BaseTypeTag _ | Ast.StructUnionTag _
+ | Ast.SignTag _
+ | Ast.StorageTag _ | Ast.ConstVolTag _ | Ast.TypeCTag _ -> false
+ (* not sure about the rest *)
+ | _ -> false in
+ List.for_all (List.for_all tester)
+
+let pr = Printf.sprintf
+
+let insert thing thinginfo into intoinfo =
+ let get_last l = let l = List.rev l in (List.rev(List.tl l),List.hd l) in
+ let get_first l = (List.hd l,List.tl l) in
+ let thing_start = thinginfo.Ast0.logical_start in
+ let thing_end = thinginfo.Ast0.logical_end in
+ let thing_offset = thinginfo.Ast0.offset in
+ let into_start = intoinfo.Ast0.tline_start in
+ let into_end = intoinfo.Ast0.tline_end in
+ let into_left_offset = intoinfo.Ast0.left_offset in
+ let into_right_offset = intoinfo.Ast0.right_offset in
+ if thing_end < into_start && thing_start < into_start
+ then (thing@into,
+ {{intoinfo with Ast0.tline_start = thing_start}
+ with Ast0.left_offset = thing_offset})
+ else if thing_end = into_start && thing_offset < into_left_offset
+ then
+ let (prev,last) = get_last thing in
+ let (first,rest) = get_first into in
+ (prev@[last@first]@rest,
+ {{intoinfo with Ast0.tline_start = thing_start}
+ with Ast0.left_offset = thing_offset})
+ else if thing_start > into_end && thing_end > into_end
+ then (into@thing,
+ {{intoinfo with Ast0.tline_end = thing_end}
+ with Ast0.right_offset = thing_offset})
+ else if thing_start = into_end && thing_offset > into_right_offset
+ then
+ let (first,rest) = get_first thing in
+ let (prev,last) = get_last into in
+ (prev@[last@first]@rest,
+ {{intoinfo with Ast0.tline_end = thing_end}
+ with Ast0.right_offset = thing_offset})
+ else
+ begin
+ Printf.printf "thing start %d thing end %d into start %d into end %d\n"
+ thing_start thing_end into_start into_end;
+ Printf.printf "thing offset %d left offset %d right offset %d\n"
+ thing_offset into_left_offset into_right_offset;
+ Pretty_print_cocci.print_anything "" thing;
+ Pretty_print_cocci.print_anything "" into;
+ failwith "can't figure out where to put the + code"
+ end
+
+let init thing info =
+ (thing,
+ {Ast0.tline_start = info.Ast0.logical_start;
+ Ast0.tline_end = info.Ast0.logical_end;
+ Ast0.left_offset = info.Ast0.offset;
+ Ast0.right_offset = info.Ast0.offset})
+
+let attachbefore (infop,p) = function
+ Ast0.MINUS(replacements) ->
+ (match !replacements with
+ ([],ti) -> replacements := init p infop
+ | (repl,ti) -> replacements := insert p infop repl ti)
+ | Ast0.CONTEXT(neighbors) ->
+ let (repl,ti1,ti2) = !neighbors in
+ (match repl with
+ Ast.BEFORE(bef) ->
+ let (bef,ti1) = insert p infop bef ti1 in
+ neighbors := (Ast.BEFORE(bef),ti1,ti2)
+ | Ast.AFTER(aft) ->
+ let (bef,ti1) = init p infop in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.BEFOREAFTER(bef,aft) ->
+ let (bef,ti1) = insert p infop bef ti1 in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.NOTHING ->
+ let (bef,ti1) = init p infop in
+ neighbors := (Ast.BEFORE(bef),ti1,ti2))
+ | _ -> failwith "not possible for attachbefore"
+
+let attachafter (infop,p) = function
+ Ast0.MINUS(replacements) ->
+ (match !replacements with
+ ([],ti) -> replacements := init p infop
+ | (repl,ti) -> replacements := insert p infop repl ti)
+ | Ast0.CONTEXT(neighbors) ->
+ let (repl,ti1,ti2) = !neighbors in
+ (match repl with
+ Ast.BEFORE(bef) ->
+ let (aft,ti2) = init p infop in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.AFTER(aft) ->
+ let (aft,ti2) = insert p infop aft ti2 in
+ neighbors := (Ast.AFTER(aft),ti1,ti2)
+ | Ast.BEFOREAFTER(bef,aft) ->
+ let (aft,ti2) = insert p infop aft ti2 in
+ neighbors := (Ast.BEFOREAFTER(bef,aft),ti1,ti2)
+ | Ast.NOTHING ->
+ let (aft,ti2) = init p infop in
+ neighbors := (Ast.AFTER(aft),ti1,ti2))
+ | _ -> failwith "not possible for attachbefore"
+
+let attach_all_before ps m =
+ List.iter (function x -> attachbefore x m) ps
+
+let attach_all_after ps m =
+ List.iter (function x -> attachafter x m) ps
+
+let split_at_end info ps =
+ let split_point = info.Ast0.logical_end in
+ List.partition
+ (function (info,_) -> info.Ast0.logical_end < split_point)
+ ps
+
+let allminus = function
+ Ast0.MINUS(_) -> true
+ | _ -> false
+
+let rec before_m1 ((f1,infom1,m1) as x1) ((f2,infom2,m2) as x2) rest = function
+ [] -> ()
+ | (((infop,_) as p) :: ps) as all ->
+ if less_than_start infop infom1 or
+ (allminus m1 && less_than_end infop infom1) (* account for trees *)
+ then
+ if good_start infom1
+ then (attachbefore p m1; before_m1 x1 x2 rest ps)
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ else after_m1 x1 x2 rest all
+
+and after_m1 ((f1,infom1,m1) as x1) ((f2,infom2,m2) as x2) rest = function
+ [] -> ()
+ | (((infop,pcode) as p) :: ps) as all ->
+ (* if the following is false, then some + code is stuck in the middle
+ of some context code (m1). could drop down to the token level.
+ this might require adjustments in ast0toast as well, when + code on
+ expressions is dropped down to + code on expressions. it might
+ also break some invariants on which iso depends, particularly on
+ what it can infer from something being CONTEXT with no top-level
+ modifications. for the moment, we thus give an error, asking the
+ user to rewrite the semantic patch. *)
+ if greater_than_end infop infom1
+ then
+ if less_than_start infop infom2
+ then
+ if predecl_code pcode && good_end infom1 && decl f1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if predecl_code pcode && good_start infom2 && decl f2
+ then before_m2 x2 rest all
+ else if top_code pcode && good_end infom1 && toplevel f1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if top_code pcode && good_start infom2 && toplevel f2
+ then before_m2 x2 rest all
+ else if good_end infom1 && favored f1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if good_start infom2 && favored f2
+ then before_m2 x2 rest all
+ else if good_end infom1
+ then (attachafter p m1; after_m1 x1 x2 rest ps)
+ else if good_start infom2
+ then before_m2 x2 rest all
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ else after_m2 x2 rest all
+ else
+ begin
+ Printf.printf "between: p start %d p end %d m1 start %d m1 end %d m2 start %d m2 end %d\n"
+ infop.Ast0.line_start infop.Ast0.line_end
+ infom1.Ast0.line_start infom1.Ast0.line_end
+ infom2.Ast0.line_start infom2.Ast0.line_end;
+ Pretty_print_cocci.print_anything "" pcode;
+ failwith
+ "The semantic patch is structured in a way that may give bad results with isomorphisms. Please try to rewrite it by moving + code out from -/context terms."
+ end
+
+and before_m2 ((f2,infom2,m2) as x2) rest
+ (p : (Ast0.info * Ast.anything list list) list) =
+ match (rest,p) with
+ (_,[]) -> ()
+ | ([],((infop,_)::_)) ->
+ let (bef_m2,aft_m2) = split_at_end infom2 p in (* bef_m2 isn't empty *)
+ if good_start infom2
+ then (attach_all_before bef_m2 m2; after_m2 x2 rest aft_m2)
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ | (m::ms,_) -> before_m1 x2 m ms p
+
+and after_m2 ((f2,infom2,m2) as x2) rest
+ (p : (Ast0.info * Ast.anything list list) list) =
+ match (rest,p) with
+ (_,[]) -> ()
+ | ([],((infop,_)::_)) ->
+ if good_end infom2
+ then attach_all_after p m2
+ else
+ failwith
+ (pr "%d: no available token to attach to" infop.Ast0.line_start)
+ | (m::ms,_) -> after_m1 x2 m ms p
+
+let merge_one : (minus_join_point * Ast0.info * 'a) list *
+ (Ast0.info * Ast.anything list list) list -> unit = function (m,p) ->
+ (*
+ Printf.printf "minus code\n";
+ List.iter
+ (function (_,info,_) ->
+ Printf.printf "start %d end %d real_start %d real_end %d\n"
+ info.Ast0.logical_start info.Ast0.logical_end
+ info.Ast0.line_start info.Ast0.line_end)
+ m;
+ Printf.printf "plus code\n";
+ List.iter
+ (function (info,p) ->
+ Printf.printf "start %d end %d real_start %d real_end %d\n"
+ info.Ast0.logical_start info.Ast0.logical_end
+ info.Ast0.line_end info.Ast0.line_end;
+ Pretty_print_cocci.print_anything "" p;
+ Format.print_newline())
+ p;
+ *)
+ match (m,p) with
+ (_,[]) -> ()
+ | (m1::m2::restm,p) -> before_m1 m1 m2 restm p
+ | ([m],p) -> before_m2 m [] p
+ | ([],_) -> failwith "minus tree ran out before the plus tree"
+
+let merge minus_list plus_list =
+ (*
+ Printf.printf "minus list %s\n"
+ (String.concat " "
+ (List.map (function (x,_) -> string_of_int x) minus_list));
+ Printf.printf "plus list %s\n"
+ (String.concat " "
+ (List.map (function (x,_) -> string_of_int x) plus_list));
+ *)
+ List.iter
+ (function (index,minus_info) ->
+ let plus_info = List.assoc index plus_list in
+ merge_one (minus_info,plus_info))
+ minus_list
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Need to check that CONTEXT nodes have nothing attached to their tokens.
+If they do, they become MIXED *)
+
+let reevaluate_contextness =
+ let bind = (@) in
+ let option_default = [] in
+
+ let mcode (_,_,_,mc,_) =
+ match mc with
+ Ast0.CONTEXT(mc) -> let (ba,_,_) = !mc in [ba]
+ | _ -> [] in
+
+ let donothing r k e =
+ match Ast0.get_mcodekind e with
+ Ast0.CONTEXT(mc) ->
+ if List.exists (function Ast.NOTHING -> false | _ -> true) (k e)
+ then Ast0.set_mcodekind e (Ast0.MIXED(mc));
+ []
+ | _ -> let _ = k e in [] in
+
+ let res =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing
+ donothing donothing donothing donothing donothing donothing donothing in
+ res.V0.combiner_top_level
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+
+let insert_plus minus plus =
+ let minus_stream = process_minus minus in
+ let plus_stream = process_plus plus in
+ merge minus_stream plus_stream;
+ List.iter (function x -> let _ = reevaluate_contextness x in ()) minus
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Potential problem: offset of mcode is not updated when an iso is
+instantiated, implying that a term may end up with many mcodes with the
+same offset. On the other hand, at the moment offset only seems to be used
+before this phase. Furthermore add_dot_binding relies on the offset to
+remain the same between matching an iso and instantiating it with bindings. *)
+
+(* --------------------------------------------------------------------- *)
+(* match a SmPL expression against a SmPL abstract syntax tree,
+either - or + *)
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+
+let current_rule = ref ""
+
+(* --------------------------------------------------------------------- *)
+
+type isomorphism =
+ Ast_cocci.metavar list * Ast0_cocci.anything list list * string (* name *)
+
+let strip_info =
+ let mcode (term,_,_,_,_) =
+ (term,Ast0.NONE,Ast0.default_info(),Ast0.PLUS,ref Ast0.NoMetaPos) in
+ let donothing r k e =
+ let x = k e in
+ {(Ast0.wrap (Ast0.unwrap x)) with
+ Ast0.mcodekind = ref Ast0.PLUS;
+ Ast0.true_if_test = x.Ast0.true_if_test} in
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing
+
+let anything_equal = function
+ (Ast0.DotsExprTag(d1),Ast0.DotsExprTag(d2)) ->
+ failwith "not a possible variable binding" (*not sure why these are pbs*)
+ | (Ast0.DotsInitTag(d1),Ast0.DotsInitTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.DotsParamTag(d1),Ast0.DotsParamTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.DotsStmtTag(d1),Ast0.DotsStmtTag(d2)) ->
+ (strip_info.V0.rebuilder_statement_dots d1) =
+ (strip_info.V0.rebuilder_statement_dots d2)
+ | (Ast0.DotsDeclTag(d1),Ast0.DotsDeclTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.DotsCaseTag(d1),Ast0.DotsCaseTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.IdentTag(d1),Ast0.IdentTag(d2)) ->
+ (strip_info.V0.rebuilder_ident d1) = (strip_info.V0.rebuilder_ident d2)
+ | (Ast0.ExprTag(d1),Ast0.ExprTag(d2)) ->
+ (strip_info.V0.rebuilder_expression d1) =
+ (strip_info.V0.rebuilder_expression d2)
+ | (Ast0.ArgExprTag(_),_) | (_,Ast0.ArgExprTag(_)) ->
+ failwith "not possible - only in isos1"
+ | (Ast0.TestExprTag(_),_) | (_,Ast0.TestExprTag(_)) ->
+ failwith "not possible - only in isos1"
+ | (Ast0.TypeCTag(d1),Ast0.TypeCTag(d2)) ->
+ (strip_info.V0.rebuilder_typeC d1) =
+ (strip_info.V0.rebuilder_typeC d2)
+ | (Ast0.InitTag(d1),Ast0.InitTag(d2)) ->
+ (strip_info.V0.rebuilder_initialiser d1) =
+ (strip_info.V0.rebuilder_initialiser d2)
+ | (Ast0.ParamTag(d1),Ast0.ParamTag(d2)) ->
+ (strip_info.V0.rebuilder_parameter d1) =
+ (strip_info.V0.rebuilder_parameter d2)
+ | (Ast0.DeclTag(d1),Ast0.DeclTag(d2)) ->
+ (strip_info.V0.rebuilder_declaration d1) =
+ (strip_info.V0.rebuilder_declaration d2)
+ | (Ast0.StmtTag(d1),Ast0.StmtTag(d2)) ->
+ (strip_info.V0.rebuilder_statement d1) =
+ (strip_info.V0.rebuilder_statement d2)
+ | (Ast0.CaseLineTag(d1),Ast0.CaseLineTag(d2)) ->
+ (strip_info.V0.rebuilder_case_line d1) =
+ (strip_info.V0.rebuilder_case_line d2)
+ | (Ast0.TopTag(d1),Ast0.TopTag(d2)) ->
+ (strip_info.V0.rebuilder_top_level d1) =
+ (strip_info.V0.rebuilder_top_level d2)
+ | (Ast0.IsoWhenTag(_),_) | (_,Ast0.IsoWhenTag(_)) ->
+ failwith "only for isos within iso phase"
+ | _ -> false
+
+let term (var1,_,_,_,_) = var1
+let dot_term (var1,_,info,_,_) = ("", var1 ^ (string_of_int info.Ast0.offset))
+
+
+type reason =
+ NotPure of Ast0.pure * (string * string) * Ast0.anything
+ | NotPureLength of (string * string)
+ | ContextRequired of Ast0.anything
+ | NonMatch
+ | Braces of Ast0.statement
+ | Position of string * string
+
+let interpret_reason name line reason printer =
+ Printf.printf
+ "warning: iso %s does not match the code below on line %d\n" name line;
+ printer(); Format.print_newline();
+ match reason with
+ NotPure(Ast0.Pure,(_,var),nonpure) ->
+ Printf.printf
+ "pure metavariable %s is matched against the following nonpure code:\n"
+ var;
+ Unparse_ast0.unparse_anything nonpure
+ | NotPure(Ast0.Context,(_,var),nonpure) ->
+ Printf.printf
+ "context metavariable %s is matched against the following\nnoncontext code:\n"
+ var;
+ Unparse_ast0.unparse_anything nonpure
+ | NotPure(Ast0.PureContext,(_,var),nonpure) ->
+ Printf.printf
+ "pure context metavariable %s is matched against the following\nnonpure or noncontext code:\n"
+ var;
+ Unparse_ast0.unparse_anything nonpure
+ | NotPureLength((_,var)) ->
+ Printf.printf
+ "pure metavariable %s is matched against too much or too little code\n"
+ var;
+ | ContextRequired(term) ->
+ Printf.printf
+ "the following code matched is not uniformly minus or context,\nor contains a disjunction:\n";
+ Unparse_ast0.unparse_anything term
+ | Braces(s) ->
+ Printf.printf "braces must be all minus (plus code allowed) or all\ncontext (plus code not allowed in the body) to match:\n";
+ Unparse_ast0.statement "" s;
+ Format.print_newline()
+ | Position(rule,name) ->
+ Printf.printf "position variable %s.%s conflicts with an isomorphism\n"
+ rule name;
+ | _ -> failwith "not possible"
+
+type 'a either = OK of 'a | Fail of reason
+
+let add_binding var exp bindings =
+ let var = term var in
+ let attempt bindings =
+ try
+ let cur = List.assoc var bindings in
+ if anything_equal(exp,cur) then [bindings] else []
+ with Not_found -> [((var,exp)::bindings)] in
+ match List.concat(List.map attempt bindings) with
+ [] -> Fail NonMatch
+ | x -> OK x
+
+let add_dot_binding var exp bindings =
+ let var = dot_term var in
+ let attempt bindings =
+ try
+ let cur = List.assoc var bindings in
+ if anything_equal(exp,cur) then [bindings] else []
+ with Not_found -> [((var,exp)::bindings)] in
+ match List.concat(List.map attempt bindings) with
+ [] -> Fail NonMatch
+ | x -> OK x
+
+(* multi-valued *)
+let add_multi_dot_binding var exp bindings =
+ let var = dot_term var in
+ let attempt bindings = [((var,exp)::bindings)] in
+ match List.concat(List.map attempt bindings) with
+ [] -> Fail NonMatch
+ | x -> OK x
+
+let rec nub ls =
+ match ls with
+ [] -> []
+ | (x::xs) when (List.mem x xs) -> nub xs
+ | (x::xs) -> x::(nub xs)
+
+(* --------------------------------------------------------------------- *)
+
+let init_env = [[]]
+
+let debug str m binding =
+ let res = m binding in
+ (match res with
+ None -> Printf.printf "%s: failed\n" str
+ | Some binding ->
+ List.iter
+ (function binding ->
+ Printf.printf "%s: %s\n" str
+ (String.concat " " (List.map (function (x,_) -> x) binding)))
+ binding);
+ res
+
+let conjunct_bindings
+ (m1 : 'binding -> 'binding either)
+ (m2 : 'binding -> 'binding either)
+ (binding : 'binding) : 'binding either =
+ match m1 binding with Fail(reason) -> Fail(reason) | OK binding -> m2 binding
+
+let rec conjunct_many_bindings = function
+ [] -> failwith "not possible"
+ | [x] -> x
+ | x::xs -> conjunct_bindings x (conjunct_many_bindings xs)
+
+let mcode_equal (x,_,_,_,_) (y,_,_,_,_) = x = y
+
+let return b binding = if b then OK binding else Fail NonMatch
+let return_false reason binding = Fail reason
+
+let match_option f t1 t2 =
+ match (t1,t2) with
+ (Some t1, Some t2) -> f t1 t2
+ | (None, None) -> return true
+ | _ -> return false
+
+let bool_match_option f t1 t2 =
+ match (t1,t2) with
+ (Some t1, Some t2) -> f t1 t2
+ | (None, None) -> true
+ | _ -> false
+
+(* context_required is for the example
+ if (
++ (int * )
+ x == NULL)
+ where we can't change x == NULL to eg NULL == x. So there can either be
+ nothing attached to the root or the term has to be all removed.
+ if would be nice if we knew more about the relationship between the - and +
+ code, because in the case where the + code is a separate statement in a
+ sequence, this is not a problem. Perhaps something could be done in
+ insert_plus
+
+ The example seems strange. Why isn't the cast attached to x?
+ *)
+let is_context e =
+ !Flag.sgrep_mode2 or (* everything is context for sgrep *)
+ (match Ast0.get_mcodekind e with
+ Ast0.CONTEXT(cell) -> true
+ | _ -> false)
+
+(* needs a special case when there is a Disj or an empty DOTS
+ the following stops at the statement level, and gives true if one
+ statement is replaced by another *)
+let rec is_pure_context s =
+ !Flag.sgrep_mode2 or (* everything is context for sgrep *)
+ (match Ast0.unwrap s with
+ Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ List.for_all
+ (function x ->
+ match Ast0.undots x with
+ [s] -> is_pure_context s
+ | _ -> false (* could we do better? *))
+ statement_dots_list
+ | _ ->
+ (match Ast0.get_mcodekind s with
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) -> true
+ | _ -> false)
+ | Ast0.MINUS(mc) ->
+ (match !mc with
+ (* do better for the common case of replacing a stmt by another one *)
+ ([[Ast.StatementTag(s)]],_) ->
+ (match Ast.unwrap s with
+ Ast.IfThen(_,_,_) -> false (* potentially dangerous *)
+ | _ -> true)
+ | (_,_) -> false)
+ | _ -> false))
+
+let is_minus e =
+ match Ast0.get_mcodekind e with Ast0.MINUS(cell) -> true | _ -> false
+
+let match_list matcher is_list_matcher do_list_match la lb =
+ let rec loop = function
+ ([],[]) -> return true
+ | ([x],lb) when is_list_matcher x -> do_list_match x lb
+ | (x::xs,y::ys) -> conjunct_bindings (matcher x y) (loop (xs,ys))
+ | _ -> return false in
+ loop (la,lb)
+
+let match_maker checks_needed context_required whencode_allowed =
+
+ let check_mcode pmc cmc binding =
+ if checks_needed
+ then
+ match Ast0.get_pos cmc with
+ (Ast0.MetaPos (name,_,_)) as x ->
+ (match Ast0.get_pos pmc with
+ Ast0.MetaPos (name1,_,_) ->
+ add_binding name1 (Ast0.MetaPosTag x) binding
+ | Ast0.NoMetaPos ->
+ let (rule,name) = Ast0.unwrap_mcode name in
+ Fail (Position(rule,name)))
+ | Ast0.NoMetaPos -> OK binding
+ else OK binding in
+
+ let match_dots matcher is_list_matcher do_list_match d1 d2 =
+ match (Ast0.unwrap d1, Ast0.unwrap d2) with
+ (Ast0.DOTS(la),Ast0.DOTS(lb))
+ | (Ast0.CIRCLES(la),Ast0.CIRCLES(lb))
+ | (Ast0.STARS(la),Ast0.STARS(lb)) ->
+ match_list matcher is_list_matcher (do_list_match d2) la lb
+ | _ -> return false in
+
+ let is_elist_matcher el =
+ match Ast0.unwrap el with Ast0.MetaExprList(_,_,_) -> true | _ -> false in
+
+ let is_plist_matcher pl =
+ match Ast0.unwrap pl with Ast0.MetaParamList(_,_,_) -> true | _ -> false in
+
+ let is_slist_matcher pl =
+ match Ast0.unwrap pl with Ast0.MetaStmtList(_,_) -> true | _ -> false in
+
+ let no_list _ = false in
+
+ let build_dots pattern data =
+ match Ast0.unwrap pattern with
+ Ast0.DOTS(_) -> Ast0.rewrap pattern (Ast0.DOTS(data))
+ | Ast0.CIRCLES(_) -> Ast0.rewrap pattern (Ast0.CIRCLES(data))
+ | Ast0.STARS(_) -> Ast0.rewrap pattern (Ast0.STARS(data)) in
+
+ let pure_sp_code =
+ let bind = Ast0.lub_pure in
+ let option_default = Ast0.Context in
+ let pure_mcodekind = function
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) -> Ast0.PureContext
+ | _ -> Ast0.Context)
+ | Ast0.MINUS(mc) ->
+ (match !mc with ([],_) -> Ast0.Pure | _ -> Ast0.Impure)
+ | _ -> Ast0.Impure in
+ let donothing r k e =
+ bind (pure_mcodekind (Ast0.get_mcodekind e)) (k e) in
+
+ let mcode m = pure_mcodekind (Ast0.get_mcode_mcodekind m) in
+
+ (* a case for everything that has a metavariable *)
+ (* pure is supposed to match only unitary metavars, not anything that
+ contains only unitary metavars *)
+ let ident r k i =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind i)) (k i))
+ (match Ast0.unwrap i with
+ Ast0.MetaId(name,_,pure) | Ast0.MetaFunc(name,_,pure)
+ | Ast0.MetaLocalFunc(name,_,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ let expression r k e =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind e)) (k e))
+ (match Ast0.unwrap e with
+ Ast0.MetaErr(name,_,pure)
+ | Ast0.MetaExpr(name,_,_,_,pure) | Ast0.MetaExprList(name,_,pure) ->
+ pure
+ | _ -> Ast0.Impure) in
+
+ let typeC r k t =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind t)) (k t))
+ (match Ast0.unwrap t with
+ Ast0.MetaType(name,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ let param r k p =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind p)) (k p))
+ (match Ast0.unwrap p with
+ Ast0.MetaParam(name,pure) | Ast0.MetaParamList(name,_,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ let stmt r k s =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind s)) (k s))
+ (match Ast0.unwrap s with
+ Ast0.MetaStmt(name,pure) | Ast0.MetaStmtList(name,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ ident expression typeC donothing param donothing stmt donothing
+ donothing in
+
+ let add_pure_list_binding name pure is_pure builder1 builder2 lst =
+ match (checks_needed,pure) with
+ (true,Ast0.Pure) | (true,Ast0.Context) | (true,Ast0.PureContext) ->
+ (match lst with
+ [x] ->
+ if (Ast0.lub_pure (is_pure x) pure) = pure
+ then add_binding name (builder1 lst)
+ else return_false (NotPure (pure,term name,builder1 lst))
+ | _ -> return_false (NotPureLength (term name)))
+ | (false,_) | (_,Ast0.Impure) -> add_binding name (builder2 lst) in
+
+ let add_pure_binding name pure is_pure builder x =
+ match (checks_needed,pure) with
+ (true,Ast0.Pure) | (true,Ast0.Context) | (true,Ast0.PureContext) ->
+ if (Ast0.lub_pure (is_pure x) pure) = pure
+ then add_binding name (builder x)
+ else return_false (NotPure (pure,term name, builder x))
+ | (false,_) | (_,Ast0.Impure) -> add_binding name (builder x) in
+
+ let do_elist_match builder el lst =
+ match Ast0.unwrap el with
+ Ast0.MetaExprList(name,lenname,pure) ->
+ (*how to handle lenname? should it be an option type and always None?*)
+ failwith "expr list pattern not supported in iso"
+ (*add_pure_list_binding name pure
+ pure_sp_code.V0.combiner_expression
+ (function lst -> Ast0.ExprTag(List.hd lst))
+ (function lst -> Ast0.DotsExprTag(build_dots builder lst))
+ lst*)
+ | _ -> failwith "not possible" in
+
+ let do_plist_match builder pl lst =
+ match Ast0.unwrap pl with
+ Ast0.MetaParamList(name,lename,pure) ->
+ failwith "param list pattern not supported in iso"
+ (*add_pure_list_binding name pure
+ pure_sp_code.V0.combiner_parameter
+ (function lst -> Ast0.ParamTag(List.hd lst))
+ (function lst -> Ast0.DotsParamTag(build_dots builder lst))
+ lst*)
+ | _ -> failwith "not possible" in
+
+ let do_slist_match builder sl lst =
+ match Ast0.unwrap sl with
+ Ast0.MetaStmtList(name,pure) ->
+ add_pure_list_binding name pure
+ pure_sp_code.V0.combiner_statement
+ (function lst -> Ast0.StmtTag(List.hd lst))
+ (function lst -> Ast0.DotsStmtTag(build_dots builder lst))
+ lst
+ | _ -> failwith "not possible" in
+
+ let do_nolist_match _ _ = failwith "not possible" in
+
+ let rec match_ident pattern id =
+ match Ast0.unwrap pattern with
+ Ast0.MetaId(name,_,pure) ->
+ (add_pure_binding name pure pure_sp_code.V0.combiner_ident
+ (function id -> Ast0.IdentTag id) id)
+ | Ast0.MetaFunc(name,_,pure) -> failwith "metafunc not supported"
+ | Ast0.MetaLocalFunc(name,_,pure) -> failwith "metalocalfunc not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context id
+ then
+ match (up,Ast0.unwrap id) with
+ (Ast0.Id(namea),Ast0.Id(nameb)) ->
+ if mcode_equal namea nameb
+ then check_mcode namea nameb
+ else return false
+ | (Ast0.OptIdent(ida),Ast0.OptIdent(idb))
+ | (Ast0.UniqueIdent(ida),Ast0.UniqueIdent(idb)) ->
+ match_ident ida idb
+ | (_,Ast0.OptIdent(idb))
+ | (_,Ast0.UniqueIdent(idb)) -> match_ident pattern idb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.IdentTag id)) in
+
+ (* should we do something about matching metavars against ...? *)
+ let rec match_expr pattern expr =
+ match Ast0.unwrap pattern with
+ Ast0.MetaExpr(name,_,ty,form,pure) ->
+ let form_ok =
+ match (form,expr) with
+ (Ast.ANY,_) -> true
+ | (Ast.CONST,e) ->
+ let rec matches e =
+ match Ast0.unwrap e with
+ Ast0.Constant(c) -> true
+ | Ast0.Cast(lp,ty,rp,e) -> matches e
+ | Ast0.SizeOfExpr(se,exp) -> true
+ | Ast0.SizeOfType(se,lp,ty,rp) -> true
+ | Ast0.MetaExpr(nm,_,_,Ast.CONST,p) ->
+ (Ast0.lub_pure p pure) = pure
+ | _ -> false in
+ matches e
+ | (Ast.ID,e) | (Ast.LocalID,e) ->
+ let rec matches e =
+ match Ast0.unwrap e with
+ Ast0.Ident(c) -> true
+ | Ast0.Cast(lp,ty,rp,e) -> matches e
+ | Ast0.MetaExpr(nm,_,_,Ast.ID,p) ->
+ (Ast0.lub_pure p pure) = pure
+ | _ -> false in
+ matches e in
+ if form_ok
+ then
+ match ty with
+ Some ts ->
+ if List.exists
+ (function Type_cocci.MetaType(_,_,_) -> true | _ -> false)
+ ts
+ then
+ (match ts with
+ [Type_cocci.MetaType(tyname,_,_)] ->
+ let expty =
+ match (Ast0.unwrap expr,Ast0.get_type expr) with
+ (* easier than updating type inferencer to manage multiple
+ types *)
+ (Ast0.MetaExpr(_,_,Some tts,_,_),_) -> Some tts
+ | (_,Some ty) -> Some [ty]
+ | _ -> None in
+ (match expty with
+ Some expty ->
+ let tyname = Ast0.rewrap_mcode name tyname in
+ (function bindings ->
+ let attempts =
+ List.map
+ (function expty ->
+ (try
+ conjunct_bindings
+ (add_pure_binding tyname Ast0.Impure
+ (function _ -> Ast0.Impure)
+ (function ty -> Ast0.TypeCTag ty)
+ (Ast0.rewrap expr
+ (Ast0.reverse_type expty)))
+ (add_pure_binding name pure
+ pure_sp_code.V0.combiner_expression
+ (function expr -> Ast0.ExprTag expr)
+ expr)
+ bindings
+ with Ast0.TyConv ->
+ Printf.printf "warning: unconvertible type";
+ return false bindings))
+ expty in
+ match
+ List.concat
+ (List.map (function Fail _ -> [] | OK x -> x)
+ attempts)
+ with
+ [] -> Fail NonMatch
+ | x -> OK x)
+ | _ ->
+ (*Printf.printf
+ "warning: type metavar can only match one type";*)
+ return false)
+ | _ ->
+ failwith
+ "mixture of metatype and other types not supported")
+ else
+ let expty = Ast0.get_type expr in
+ if List.exists (function t -> Type_cocci.compatible t expty) ts
+ then
+ add_pure_binding name pure
+ pure_sp_code.V0.combiner_expression
+ (function expr -> Ast0.ExprTag expr)
+ expr
+ else return false
+ | None ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_expression
+ (function expr -> Ast0.ExprTag expr)
+ expr
+ else return false
+ | Ast0.MetaErr(namea,_,pure) -> failwith "metaerr not supported"
+ | Ast0.MetaExprList(_,_,_) -> failwith "metaexprlist not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context expr
+ then
+ match (up,Ast0.unwrap expr) with
+ (Ast0.Ident(ida),Ast0.Ident(idb)) ->
+ match_ident ida idb
+ | (Ast0.Constant(consta),Ast0.Constant(constb)) ->
+ if mcode_equal consta constb
+ then check_mcode consta constb
+ else return false
+ | (Ast0.FunCall(fna,lp1,argsa,rp1),Ast0.FunCall(fnb,lp,argsb,rp)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp; match_expr fna fnb;
+ match_dots match_expr is_elist_matcher do_elist_match
+ argsa argsb]
+ | (Ast0.Assignment(lefta,opa,righta,_),
+ Ast0.Assignment(leftb,opb,rightb,_)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_many_bindings
+ [check_mcode opa opb; match_expr lefta leftb;
+ match_expr righta rightb]
+ else return false
+ | (Ast0.CondExpr(exp1a,lp1,exp2a,rp1,exp3a),
+ Ast0.CondExpr(exp1b,lp,exp2b,rp,exp3b)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ match_expr exp1a exp1b; match_option match_expr exp2a exp2b;
+ match_expr exp3a exp3b]
+ | (Ast0.Postfix(expa,opa),Ast0.Postfix(expb,opb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_bindings (check_mcode opa opb) (match_expr expa expb)
+ else return false
+ | (Ast0.Infix(expa,opa),Ast0.Infix(expb,opb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_bindings (check_mcode opa opb) (match_expr expa expb)
+ else return false
+ | (Ast0.Unary(expa,opa),Ast0.Unary(expb,opb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_bindings (check_mcode opa opb) (match_expr expa expb)
+ else return false
+ | (Ast0.Binary(lefta,opa,righta),Ast0.Binary(leftb,opb,rightb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_many_bindings
+ [check_mcode opa opb; match_expr lefta leftb;
+ match_expr righta rightb]
+ else return false
+ | (Ast0.Paren(lp1,expa,rp1),Ast0.Paren(lp,expb,rp)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp; match_expr expa expb]
+ | (Ast0.ArrayAccess(exp1a,lb1,exp2a,rb1),
+ Ast0.ArrayAccess(exp1b,lb,exp2b,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_expr exp1a exp1b; match_expr exp2a exp2b]
+ | (Ast0.RecordAccess(expa,opa,fielda),
+ Ast0.RecordAccess(expb,op,fieldb))
+ | (Ast0.RecordPtAccess(expa,opa,fielda),
+ Ast0.RecordPtAccess(expb,op,fieldb)) ->
+ conjunct_many_bindings
+ [check_mcode opa op; match_expr expa expb;
+ match_ident fielda fieldb]
+ | (Ast0.Cast(lp1,tya,rp1,expa),Ast0.Cast(lp,tyb,rp,expb)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ match_typeC tya tyb; match_expr expa expb]
+ | (Ast0.SizeOfExpr(szf1,expa),Ast0.SizeOfExpr(szf,expb)) ->
+ conjunct_bindings (check_mcode szf1 szf) (match_expr expa expb)
+ | (Ast0.SizeOfType(szf1,lp1,tya,rp1),
+ Ast0.SizeOfType(szf,lp,tyb,rp)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode szf1 szf; match_typeC tya tyb]
+ | (Ast0.TypeExp(tya),Ast0.TypeExp(tyb)) ->
+ match_typeC tya tyb
+ | (Ast0.EComma(cm1),Ast0.EComma(cm)) -> check_mcode cm1 cm
+ | (Ast0.DisjExpr(_,expsa,_,_),_) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.NestExpr(_,exp_dotsa,_,_,_),_) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.Edots(d,None),Ast0.Edots(d1,None))
+ | (Ast0.Ecircles(d,None),Ast0.Ecircles(d1,None))
+ | (Ast0.Estars(d,None),Ast0.Estars(d1,None)) -> check_mcode d d1
+ | (Ast0.Edots(ed,None),Ast0.Edots(ed1,Some wc))
+ | (Ast0.Ecircles(ed,None),Ast0.Ecircles(ed1,Some wc))
+ | (Ast0.Estars(ed,None),Ast0.Estars(ed1,Some wc)) ->
+ (* hope that mcode of edots is unique somehow *)
+ conjunct_bindings (check_mcode ed ed1)
+ (let (edots_whencode_allowed,_,_) = whencode_allowed in
+ if edots_whencode_allowed
+ then add_dot_binding ed (Ast0.ExprTag wc)
+ else
+ (Printf.printf
+ "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Edots(_,Some _),_) | (Ast0.Ecircles(_,Some _),_)
+ | (Ast0.Estars(_,Some _),_) ->
+ failwith "whencode not allowed in a pattern1"
+ | (Ast0.OptExp(expa),Ast0.OptExp(expb))
+ | (Ast0.UniqueExp(expa),Ast0.UniqueExp(expb)) -> match_expr expa expb
+ | (_,Ast0.OptExp(expb))
+ | (_,Ast0.UniqueExp(expb)) -> match_expr pattern expb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.ExprTag expr))
+
+(* the special case for function types prevents the eg T X; -> T X = E; iso
+ from applying, which doesn't seem very relevant, but it also avoids a
+ mysterious bug that is obtained with eg int attach(...); *)
+ and match_typeC pattern t =
+ match Ast0.unwrap pattern with
+ Ast0.MetaType(name,pure) ->
+ (match Ast0.unwrap t with
+ Ast0.FunctionType(tya,lp1a,paramsa,rp1a) -> return false
+ | _ ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_typeC
+ (function ty -> Ast0.TypeCTag ty)
+ t)
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context t
+ then
+ match (up,Ast0.unwrap t) with
+ (Ast0.ConstVol(cva,tya),Ast0.ConstVol(cvb,tyb)) ->
+ if mcode_equal cva cvb
+ then
+ conjunct_bindings (check_mcode cva cvb) (match_typeC tya tyb)
+ else return false
+ | (Ast0.BaseType(tya,signa),Ast0.BaseType(tyb,signb)) ->
+ if (mcode_equal tya tyb &&
+ bool_match_option mcode_equal signa signb)
+ then
+ conjunct_bindings (check_mcode tya tyb)
+ (match_option check_mcode signa signb)
+ else return false
+ | (Ast0.ImplicitInt(signa),Ast0.ImplicitInt(signb)) ->
+ if mcode_equal signa signb
+ then check_mcode signa signb
+ else return false
+ | (Ast0.Pointer(tya,star1),Ast0.Pointer(tyb,star)) ->
+ conjunct_bindings (check_mcode star1 star) (match_typeC tya tyb)
+ | (Ast0.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a),
+ Ast0.FunctionPointer(tyb,lp1b,starb,rp1b,lp2b,paramsb,rp2b)) ->
+ conjunct_many_bindings
+ [check_mcode stara starb; check_mcode lp1a lp1b;
+ check_mcode rp1a rp1b; check_mcode lp2a lp2b;
+ check_mcode rp2a rp2b; match_typeC tya tyb;
+ match_dots match_param is_plist_matcher
+ do_plist_match paramsa paramsb]
+ | (Ast0.FunctionType(tya,lp1a,paramsa,rp1a),
+ Ast0.FunctionType(tyb,lp1b,paramsb,rp1b)) ->
+ conjunct_many_bindings
+ [check_mcode lp1a lp1b; check_mcode rp1a rp1b;
+ match_option match_typeC tya tyb;
+ match_dots match_param is_plist_matcher do_plist_match
+ paramsa paramsb]
+ | (Ast0.Array(tya,lb1,sizea,rb1),Ast0.Array(tyb,lb,sizeb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_typeC tya tyb; match_option match_expr sizea sizeb]
+ | (Ast0.StructUnionName(kinda,Some namea),
+ Ast0.StructUnionName(kindb,Some nameb)) ->
+ if mcode_equal kinda kindb
+ then
+ conjunct_bindings (check_mcode kinda kindb)
+ (match_ident namea nameb)
+ else return false
+ | (Ast0.StructUnionDef(tya,lb1,declsa,rb1),
+ Ast0.StructUnionDef(tyb,lb,declsb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_typeC tya tyb;
+ match_dots match_decl no_list do_nolist_match declsa declsb]
+ | (Ast0.TypeName(namea),Ast0.TypeName(nameb)) ->
+ if mcode_equal namea nameb
+ then check_mcode namea nameb
+ else return false
+ | (Ast0.DisjType(_,typesa,_,_),Ast0.DisjType(_,typesb,_,_)) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.OptType(tya),Ast0.OptType(tyb))
+ | (Ast0.UniqueType(tya),Ast0.UniqueType(tyb)) -> match_typeC tya tyb
+ | (_,Ast0.OptType(tyb))
+ | (_,Ast0.UniqueType(tyb)) -> match_typeC pattern tyb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.TypeCTag t))
+
+ and match_decl pattern d =
+ if not(checks_needed) or not(context_required) or is_context d
+ then
+ match (Ast0.unwrap pattern,Ast0.unwrap d) with
+ (Ast0.Init(stga,tya,ida,eq1,inia,sc1),
+ Ast0.Init(stgb,tyb,idb,eq,inib,sc)) ->
+ if bool_match_option mcode_equal stga stgb
+ then
+ conjunct_many_bindings
+ [check_mcode eq1 eq; check_mcode sc1 sc;
+ match_option check_mcode stga stgb;
+ match_typeC tya tyb; match_ident ida idb;
+ match_init inia inib]
+ else return false
+ | (Ast0.UnInit(stga,tya,ida,sc1),Ast0.UnInit(stgb,tyb,idb,sc)) ->
+ if bool_match_option mcode_equal stga stgb
+ then
+ conjunct_many_bindings
+ [check_mcode sc1 sc; match_option check_mcode stga stgb;
+ match_typeC tya tyb; match_ident ida idb]
+ else return false
+ | (Ast0.MacroDecl(namea,lp1,argsa,rp1,sc1),
+ Ast0.MacroDecl(nameb,lp,argsb,rp,sc)) ->
+ conjunct_many_bindings
+ [match_ident namea nameb;
+ check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode sc1 sc;
+ match_dots match_expr is_elist_matcher do_elist_match
+ argsa argsb]
+ | (Ast0.TyDecl(tya,sc1),Ast0.TyDecl(tyb,sc)) ->
+ conjunct_bindings (check_mcode sc1 sc) (match_typeC tya tyb)
+ | (Ast0.Typedef(stga,tya,ida,sc1),Ast0.Typedef(stgb,tyb,idb,sc)) ->
+ conjunct_bindings (check_mcode sc1 sc)
+ (conjunct_bindings (match_typeC tya tyb) (match_typeC ida idb))
+ | (Ast0.DisjDecl(_,declsa,_,_),Ast0.DisjDecl(_,declsb,_,_)) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.Ddots(d1,None),Ast0.Ddots(d,None)) -> check_mcode d1 d
+ | (Ast0.Ddots(dd,None),Ast0.Ddots(d,Some wc)) ->
+ conjunct_bindings (check_mcode dd d)
+ (* hope that mcode of ddots is unique somehow *)
+ (let (ddots_whencode_allowed,_,_) = whencode_allowed in
+ if ddots_whencode_allowed
+ then add_dot_binding dd (Ast0.DeclTag wc)
+ else
+ (Printf.printf "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Ddots(_,Some _),_) ->
+ failwith "whencode not allowed in a pattern1"
+
+ | (Ast0.OptDecl(decla),Ast0.OptDecl(declb))
+ | (Ast0.UniqueDecl(decla),Ast0.UniqueDecl(declb)) ->
+ match_decl decla declb
+ | (_,Ast0.OptDecl(declb))
+ | (_,Ast0.UniqueDecl(declb)) ->
+ match_decl pattern declb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.DeclTag d))
+
+ and match_init pattern i =
+ if not(checks_needed) or not(context_required) or is_context i
+ then
+ match (Ast0.unwrap pattern,Ast0.unwrap i) with
+ (Ast0.InitExpr(expa),Ast0.InitExpr(expb)) ->
+ match_expr expa expb
+ | (Ast0.InitList(lb1,initlista,rb1),Ast0.InitList(lb,initlistb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_dots match_init no_list do_nolist_match
+ initlista initlistb]
+ | (Ast0.InitGccDotName(d1,namea,e1,inia),
+ Ast0.InitGccDotName(d,nameb,e,inib)) ->
+ conjunct_many_bindings
+ [check_mcode d1 d; check_mcode e1 e;
+ match_ident namea nameb; match_init inia inib]
+ | (Ast0.InitGccName(namea,c1,inia),Ast0.InitGccName(nameb,c,inib)) ->
+ conjunct_many_bindings
+ [check_mcode c1 c; match_ident namea nameb;
+ match_init inia inib]
+ | (Ast0.InitGccIndex(lb1,expa,rb1,e1,inia),
+ Ast0.InitGccIndex(lb2,expb,rb2,e2,inib)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb2; check_mcode rb1 rb2; check_mcode e1 e2;
+ match_expr expa expb; match_init inia inib]
+ | (Ast0.InitGccRange(lb1,exp1a,d1,exp2a,rb1,e1,inia),
+ Ast0.InitGccRange(lb2,exp1b,d2,exp2b,rb2,e2,inib)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb2; check_mcode d1 d2;
+ check_mcode rb1 rb2; check_mcode e1 e2;
+ match_expr exp1a exp1b; match_expr exp2a exp2b;
+ match_init inia inib]
+ | (Ast0.IComma(c1),Ast0.IComma(c)) -> check_mcode c1 c
+ | (Ast0.Idots(d1,None),Ast0.Idots(d,None)) -> check_mcode d1 d
+ | (Ast0.Idots(id,None),Ast0.Idots(d,Some wc)) ->
+ conjunct_bindings (check_mcode id d)
+ (* hope that mcode of edots is unique somehow *)
+ (let (_,idots_whencode_allowed,_) = whencode_allowed in
+ if idots_whencode_allowed
+ then add_dot_binding id (Ast0.InitTag wc)
+ else
+ (Printf.printf "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Idots(_,Some _),_) ->
+ failwith "whencode not allowed in a pattern2"
+ | (Ast0.OptIni(ia),Ast0.OptIni(ib))
+ | (Ast0.UniqueIni(ia),Ast0.UniqueIni(ib)) -> match_init ia ib
+ | (_,Ast0.OptIni(ib))
+ | (_,Ast0.UniqueIni(ib)) -> match_init pattern ib
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.InitTag i))
+
+ and match_param pattern p =
+ match Ast0.unwrap pattern with
+ Ast0.MetaParam(name,pure) ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_parameter
+ (function p -> Ast0.ParamTag p)
+ p
+ | Ast0.MetaParamList(name,_,pure) -> failwith "metaparamlist not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context p
+ then
+ match (up,Ast0.unwrap p) with
+ (Ast0.VoidParam(tya),Ast0.VoidParam(tyb)) -> match_typeC tya tyb
+ | (Ast0.Param(tya,ida),Ast0.Param(tyb,idb)) ->
+ conjunct_bindings (match_typeC tya tyb)
+ (match_option match_ident ida idb)
+ | (Ast0.PComma(c1),Ast0.PComma(c)) -> check_mcode c1 c
+ | (Ast0.Pdots(d1),Ast0.Pdots(d))
+ | (Ast0.Pcircles(d1),Ast0.Pcircles(d)) -> check_mcode d1 d
+ | (Ast0.OptParam(parama),Ast0.OptParam(paramb))
+ | (Ast0.UniqueParam(parama),Ast0.UniqueParam(paramb)) ->
+ match_param parama paramb
+ | (_,Ast0.OptParam(paramb))
+ | (_,Ast0.UniqueParam(paramb)) -> match_param pattern paramb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.ParamTag p))
+
+ and match_statement pattern s =
+ match Ast0.unwrap pattern with
+ Ast0.MetaStmt(name,pure) ->
+ (match Ast0.unwrap s with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_) ->
+ return false (* ... is not a single statement *)
+ | _ ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_statement
+ (function ty -> Ast0.StmtTag ty)
+ s)
+ | Ast0.MetaStmtList(name,pure) -> failwith "metastmtlist not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context s
+ then
+ match (up,Ast0.unwrap s) with
+ (Ast0.FunDecl(_,fninfoa,namea,lp1,paramsa,rp1,lb1,bodya,rb1),
+ Ast0.FunDecl(_,fninfob,nameb,lp,paramsb,rp,lb,bodyb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode lb1 lb; check_mcode rb1 rb;
+ match_fninfo fninfoa fninfob; match_ident namea nameb;
+ match_dots match_param is_plist_matcher do_plist_match
+ paramsa paramsb;
+ match_dots match_statement is_slist_matcher do_slist_match
+ bodya bodyb]
+ | (Ast0.Decl(_,decla),Ast0.Decl(_,declb)) ->
+ match_decl decla declb
+ | (Ast0.Seq(lb1,bodya,rb1),Ast0.Seq(lb,bodyb,rb)) ->
+ (* seqs can only match if they are all minus (plus code
+ allowed) or all context (plus code not allowed in the body).
+ we could be more permissive if the expansions of the isos are
+ also all seqs, but this would be hard to check except at top
+ level, and perhaps not worth checking even in that case.
+ Overall, the issue is that braces are used where single
+ statements are required, and something not satisfying these
+ conditions can cause a single statement to become a
+ non-single statement after the transformation.
+
+ example: if { ... -foo(); ... }
+ if we let the sequence convert to just -foo();
+ then we produce invalid code. For some reason,
+ single_statement can't deal with this case, perhaps because
+ it starts introducing too many braces? don't remember the
+ exact problem...
+ *)
+ conjunct_bindings (check_mcode lb1 lb)
+ (conjunct_bindings (check_mcode rb1 rb)
+ (if not(checks_needed) or is_minus s or
+ (is_context s &&
+ List.for_all is_pure_context (Ast0.undots bodyb))
+ then
+ match_dots match_statement is_slist_matcher do_slist_match
+ bodya bodyb
+ else return_false (Braces(s))))
+ | (Ast0.ExprStatement(expa,sc1),Ast0.ExprStatement(expb,sc)) ->
+ conjunct_bindings (check_mcode sc1 sc) (match_expr expa expb)
+ | (Ast0.IfThen(if1,lp1,expa,rp1,branch1a,_),
+ Ast0.IfThen(if2,lp2,expb,rp2,branch1b,_)) ->
+ conjunct_many_bindings
+ [check_mcode if1 if2; check_mcode lp1 lp2;
+ check_mcode rp1 rp2;
+ match_expr expa expb;
+ match_statement branch1a branch1b]
+ | (Ast0.IfThenElse(if1,lp1,expa,rp1,branch1a,e1,branch2a,_),
+ Ast0.IfThenElse(if2,lp2,expb,rp2,branch1b,e2,branch2b,_)) ->
+ conjunct_many_bindings
+ [check_mcode if1 if2; check_mcode lp1 lp2;
+ check_mcode rp1 rp2; check_mcode e1 e2;
+ match_expr expa expb;
+ match_statement branch1a branch1b;
+ match_statement branch2a branch2b]
+ | (Ast0.While(w1,lp1,expa,rp1,bodya,_),
+ Ast0.While(w,lp,expb,rp,bodyb,_)) ->
+ conjunct_many_bindings
+ [check_mcode w1 w; check_mcode lp1 lp;
+ check_mcode rp1 rp; match_expr expa expb;
+ match_statement bodya bodyb]
+ | (Ast0.Do(d1,bodya,w1,lp1,expa,rp1,_),
+ Ast0.Do(d,bodyb,w,lp,expb,rp,_)) ->
+ conjunct_many_bindings
+ [check_mcode d1 d; check_mcode w1 w; check_mcode lp1 lp;
+ check_mcode rp1 rp; match_statement bodya bodyb;
+ match_expr expa expb]
+ | (Ast0.For(f1,lp1,e1a,sc1a,e2a,sc2a,e3a,rp1,bodya,_),
+ Ast0.For(f,lp,e1b,sc1b,e2b,sc2b,e3b,rp,bodyb,_)) ->
+ conjunct_many_bindings
+ [check_mcode f1 f; check_mcode lp1 lp; check_mcode sc1a sc1b;
+ check_mcode sc2a sc2b; check_mcode rp1 rp;
+ match_option match_expr e1a e1b;
+ match_option match_expr e2a e2b;
+ match_option match_expr e3a e3b;
+ match_statement bodya bodyb]
+ | (Ast0.Iterator(nma,lp1,argsa,rp1,bodya,_),
+ Ast0.Iterator(nmb,lp,argsb,rp,bodyb,_)) ->
+ conjunct_many_bindings
+ [match_ident nma nmb;
+ check_mcode lp1 lp; check_mcode rp1 rp;
+ match_dots match_expr is_elist_matcher do_elist_match
+ argsa argsb;
+ match_statement bodya bodyb]
+ | (Ast0.Switch(s1,lp1,expa,rp1,lb1,casesa,rb1),
+ Ast0.Switch(s,lp,expb,rp,lb,casesb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode s1 s; check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode lb1 lb; check_mcode rb1 rb;
+ match_expr expa expb;
+ match_dots match_case_line no_list do_nolist_match
+ casesa casesb]
+ | (Ast0.Break(b1,sc1),Ast0.Break(b,sc))
+ | (Ast0.Continue(b1,sc1),Ast0.Continue(b,sc)) ->
+ conjunct_bindings (check_mcode b1 b) (check_mcode sc1 sc)
+ | (Ast0.Label(l1,c1),Ast0.Label(l2,c)) ->
+ conjunct_bindings (match_ident l1 l2) (check_mcode c1 c)
+ | (Ast0.Goto(g1,l1,sc1),Ast0.Goto(g,l2,sc)) ->
+ conjunct_many_bindings
+ [check_mcode g1 g; check_mcode sc1 sc; match_ident l1 l2]
+ | (Ast0.Return(r1,sc1),Ast0.Return(r,sc)) ->
+ conjunct_bindings (check_mcode r1 r) (check_mcode sc1 sc)
+ | (Ast0.ReturnExpr(r1,expa,sc1),Ast0.ReturnExpr(r,expb,sc)) ->
+ conjunct_many_bindings
+ [check_mcode r1 r; check_mcode sc1 sc; match_expr expa expb]
+ | (Ast0.Disj(_,statement_dots_lista,_,_),_) ->
+ failwith "disj not supported in patterns"
+ | (Ast0.Nest(_,stmt_dotsa,_,_,_),_) ->
+ failwith "nest not supported in patterns"
+ | (Ast0.Exp(expa),Ast0.Exp(expb)) -> match_expr expa expb
+ | (Ast0.TopExp(expa),Ast0.TopExp(expb)) -> match_expr expa expb
+ | (Ast0.Exp(expa),Ast0.TopExp(expb)) -> match_expr expa expb
+ | (Ast0.Ty(tya),Ast0.Ty(tyb)) -> match_typeC tya tyb
+ | (Ast0.Dots(d,[]),Ast0.Dots(d1,wc))
+ | (Ast0.Circles(d,[]),Ast0.Circles(d1,wc))
+ | (Ast0.Stars(d,[]),Ast0.Stars(d1,wc)) ->
+ (match wc with
+ [] -> check_mcode d d1
+ | _ ->
+ let (_,_,dots_whencode_allowed) = whencode_allowed in
+ if dots_whencode_allowed
+ then
+ conjunct_bindings (check_mcode d d1)
+ (List.fold_left
+ (function prev ->
+ function
+ | Ast0.WhenNot wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.DotsStmtTag wc))
+ | Ast0.WhenAlways wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d (Ast0.StmtTag wc))
+ | Ast0.WhenModifier(x) ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.IsoWhenTag x)))
+ (return true) wc)
+ else
+ (Printf.printf
+ "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Dots(_,_::_),_) | (Ast0.Circles(_,_::_),_)
+ | (Ast0.Stars(_,_::_),_) ->
+ failwith "whencode not allowed in a pattern3"
+ | (Ast0.OptStm(rea),Ast0.OptStm(reb))
+ | (Ast0.UniqueStm(rea),Ast0.UniqueStm(reb)) ->
+ match_statement rea reb
+ | (_,Ast0.OptStm(reb))
+ | (_,Ast0.UniqueStm(reb)) -> match_statement pattern reb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.StmtTag s))
+
+ (* first should provide a subset of the information in the second *)
+ and match_fninfo patterninfo cinfo =
+ let patterninfo = List.sort compare patterninfo in
+ let cinfo = List.sort compare cinfo in
+ let rec loop = function
+ (Ast0.FStorage(sta)::resta,Ast0.FStorage(stb)::restb) ->
+ if mcode_equal sta stb
+ then conjunct_bindings (check_mcode sta stb) (loop (resta,restb))
+ else return false
+ | (Ast0.FType(tya)::resta,Ast0.FType(tyb)::restb) ->
+ conjunct_bindings (match_typeC tya tyb) (loop (resta,restb))
+ | (Ast0.FInline(ia)::resta,Ast0.FInline(ib)::restb) ->
+ if mcode_equal ia ib
+ then conjunct_bindings (check_mcode ia ib) (loop (resta,restb))
+ else return false
+ | (Ast0.FAttr(ia)::resta,Ast0.FAttr(ib)::restb) ->
+ if mcode_equal ia ib
+ then conjunct_bindings (check_mcode ia ib) (loop (resta,restb))
+ else return false
+ | (x::resta,((y::_) as restb)) ->
+ (match compare x y with
+ -1 -> return false
+ | 1 -> loop (resta,restb)
+ | _ -> failwith "not possible")
+ | _ -> return false in
+ loop (patterninfo,cinfo)
+
+ and match_case_line pattern c =
+ if not(checks_needed) or not(context_required) or is_context c
+ then
+ match (Ast0.unwrap pattern,Ast0.unwrap c) with
+ (Ast0.Default(d1,c1,codea),Ast0.Default(d,c,codeb)) ->
+ conjunct_many_bindings
+ [check_mcode d1 d; check_mcode c1 c;
+ match_dots match_statement is_slist_matcher do_slist_match
+ codea codeb]
+ | (Ast0.Case(ca1,expa,c1,codea),Ast0.Case(ca,expb,c,codeb)) ->
+ conjunct_many_bindings
+ [check_mcode ca1 ca; check_mcode c1 c; match_expr expa expb;
+ match_dots match_statement is_slist_matcher do_slist_match
+ codea codeb]
+ | (Ast0.OptCase(ca),Ast0.OptCase(cb)) -> match_case_line ca cb
+ | (_,Ast0.OptCase(cb)) -> match_case_line pattern cb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.CaseLineTag c)) in
+
+ let match_statement_dots x y =
+ match_dots match_statement is_slist_matcher do_slist_match x y in
+
+ (match_expr, match_decl, match_statement, match_typeC,
+ match_statement_dots)
+
+let match_expr dochecks context_required whencode_allowed =
+ let (fn,_,_,_,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_decl dochecks context_required whencode_allowed =
+ let (_,fn,_,_,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_statement dochecks context_required whencode_allowed =
+ let (_,_,fn,_,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_typeC dochecks context_required whencode_allowed =
+ let (_,_,_,fn,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_statement_dots dochecks context_required whencode_allowed =
+ let (_,_,_,_,fn) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+(* --------------------------------------------------------------------- *)
+(* make an entire tree MINUS *)
+
+let make_minus =
+ let mcode (term,arity,info,mcodekind,pos) =
+ let new_mcodekind =
+ match mcodekind with
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) -> Ast0.MINUS(ref([],Ast0.default_token_info))
+ | _ -> failwith "make_minus: unexpected befaft")
+ | Ast0.MINUS(mc) -> mcodekind (* in the part copied from the src term *)
+ | _ -> failwith "make_minus mcode: unexpected mcodekind" in
+ (term,arity,info,new_mcodekind,pos) in
+
+ let update_mc mcodekind e =
+ match !mcodekind with
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) ->
+ mcodekind := Ast0.MINUS(ref([],Ast0.default_token_info))
+ | _ -> failwith "make_minus: unexpected befaft")
+ | Ast0.MINUS(_mc) -> () (* in the part copied from the src term *)
+ | Ast0.PLUS -> failwith "make_minus donothing: unexpected plus mcodekind"
+ | _ -> failwith "make_minus donothing: unexpected mcodekind" in
+
+ let donothing r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ let e = k e in update_mc mcodekind e; e in
+
+ (* special case for whencode, because it isn't processed by contextneg,
+ since it doesn't appear in the + code *)
+ (* cases for dots and nests *)
+ let expression r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Edots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Edots(mcode d,whencode))
+ | Ast0.Ecircles(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Ecircles(mcode d,whencode))
+ | Ast0.Estars(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Estars(mcode d,whencode))
+ | Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ update_mc mcodekind e;
+ Ast0.rewrap e
+ (Ast0.NestExpr(mcode starter,
+ r.V0.rebuilder_expression_dots expr_dots,
+ mcode ender,whencode,multi))
+ | _ -> donothing r k e in
+
+ let declaration r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Ddots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Ddots(mcode d,whencode))
+ | _ -> donothing r k e in
+
+ let statement r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Dots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Dots(mcode d,whencode))
+ | Ast0.Circles(d,whencode) ->
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Circles(mcode d,whencode))
+ | Ast0.Stars(d,whencode) ->
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Stars(mcode d,whencode))
+ | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
+ update_mc mcodekind e;
+ Ast0.rewrap e
+ (Ast0.Nest(mcode starter,r.V0.rebuilder_statement_dots stmt_dots,
+ mcode ender,whencode,multi))
+ | _ -> donothing r k e in
+
+ let initialiser r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Idots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Idots(mcode d,whencode))
+ | _ -> donothing r k e in
+
+ let dots r k e =
+ let info = Ast0.get_info e in
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.DOTS([]) ->
+ (* if context is - this should be - as well. There are no tokens
+ here though, so the bottom-up minusifier in context_neg leaves it
+ as mixed. It would be better to fix context_neg, but that would
+ require a special case for each term with a dots subterm. *)
+ (match !mcodekind with
+ Ast0.MIXED(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) ->
+ mcodekind := Ast0.MINUS(ref([],Ast0.default_token_info));
+ e
+ | _ -> failwith "make_minus: unexpected befaft")
+ (* code already processed by an enclosing iso *)
+ | Ast0.MINUS(mc) -> e
+ | _ ->
+ failwith
+ (Printf.sprintf
+ "%d: make_minus donothingxxx: unexpected mcodekind"
+ info.Ast0.line_start))
+ | _ -> donothing r k e in
+
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ dots dots dots dots dots dots
+ donothing expression donothing initialiser donothing declaration
+ statement donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* rebuild mcode cells in an instantiated alt *)
+
+(* mcodes will be side effected later with plus code, so we have to copy
+ them on instantiating an isomorphism. One could wonder whether it would
+ be better not to use side-effects, but they are convenient for insert_plus
+ where is it useful to manipulate a list of the mcodes but side-effect a
+ tree *)
+(* hmm... Insert_plus is called before Iso_pattern... *)
+let rebuild_mcode start_line =
+ let copy_mcodekind = function
+ Ast0.CONTEXT(mc) -> Ast0.CONTEXT(ref (!mc))
+ | Ast0.MINUS(mc) -> Ast0.MINUS(ref (!mc))
+ | Ast0.MIXED(mc) -> Ast0.MIXED(ref (!mc))
+ | Ast0.PLUS ->
+ (* this function is used elsewhere where we need to rebuild the
+ indices, and so we allow PLUS code as well *)
+ Ast0.PLUS in
+
+ let mcode (term,arity,info,mcodekind,pos) =
+ let info =
+ match start_line with
+ Some x -> {info with Ast0.line_start = x; Ast0.line_end = x}
+ | None -> info in
+ (term,arity,info,copy_mcodekind mcodekind,pos) in
+
+ let copy_one x =
+ let old_info = Ast0.get_info x in
+ let info =
+ match start_line with
+ Some x -> {old_info with Ast0.line_start = x; Ast0.line_end = x}
+ | None -> old_info in
+ {x with Ast0.info = info; Ast0.index = ref(Ast0.get_index x);
+ Ast0.mcodekind = ref (copy_mcodekind (Ast0.get_mcodekind x))} in
+
+ let donothing r k e = copy_one (k e) in
+
+ (* case for control operators (if, etc) *)
+ let statement r k e =
+ let s = k e in
+ let res =
+ copy_one
+ (Ast0.rewrap s
+ (match Ast0.unwrap s with
+ Ast0.Decl((info,mc),decl) ->
+ Ast0.Decl((info,copy_mcodekind mc),decl)
+ | Ast0.IfThen(iff,lp,tst,rp,branch,(info,mc)) ->
+ Ast0.IfThen(iff,lp,tst,rp,branch,(info,copy_mcodekind mc))
+ | Ast0.IfThenElse(iff,lp,tst,rp,branch1,els,branch2,(info,mc)) ->
+ Ast0.IfThenElse(iff,lp,tst,rp,branch1,els,branch2,
+ (info,copy_mcodekind mc))
+ | Ast0.While(whl,lp,exp,rp,body,(info,mc)) ->
+ Ast0.While(whl,lp,exp,rp,body,(info,copy_mcodekind mc))
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,mc)) ->
+ Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,
+ (info,copy_mcodekind mc))
+ | Ast0.Iterator(nm,lp,args,rp,body,(info,mc)) ->
+ Ast0.Iterator(nm,lp,args,rp,body,(info,copy_mcodekind mc))
+ | Ast0.FunDecl
+ ((info,mc),fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ Ast0.FunDecl
+ ((info,copy_mcodekind mc),
+ fninfo,name,lp,params,rp,lbrace,body,rbrace)
+ | s -> s)) in
+ Ast0.set_dots_bef_aft res
+ (match Ast0.get_dots_bef_aft res with
+ Ast0.NoDots -> Ast0.NoDots
+ | Ast0.AddingBetweenDots s ->
+ Ast0.AddingBetweenDots(r.V0.rebuilder_statement s)
+ | Ast0.DroppingBetweenDots s ->
+ Ast0.DroppingBetweenDots(r.V0.rebuilder_statement s)) in
+
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing
+ donothing statement donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* The problem of whencode. If an isomorphism contains dots in multiple
+ rules, then the code that is matched cannot contain whencode, because we
+ won't know which dots it goes with. Should worry about nests, but they
+ aren't allowed in isomorphisms for the moment. *)
+
+let count_edots =
+ let mcode x = 0 in
+ let option_default = 0 in
+ let bind x y = x + y in
+ let donothing r k e = k e in
+ let exprfn r k e =
+ match Ast0.unwrap e with
+ Ast0.Edots(_,_) | Ast0.Ecircles(_,_) | Ast0.Estars(_,_) -> 1
+ | _ -> 0 in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing exprfn donothing donothing donothing donothing donothing
+ donothing donothing
+
+let count_idots =
+ let mcode x = 0 in
+ let option_default = 0 in
+ let bind x y = x + y in
+ let donothing r k e = k e in
+ let initfn r k e =
+ match Ast0.unwrap e with Ast0.Idots(_,_) -> 1 | _ -> 0 in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing initfn donothing donothing donothing
+ donothing donothing
+
+let count_dots =
+ let mcode x = 0 in
+ let option_default = 0 in
+ let bind x y = x + y in
+ let donothing r k e = k e in
+ let stmtfn r k e =
+ match Ast0.unwrap e with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_) -> 1
+ | _ -> 0 in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing stmtfn
+ donothing donothing
+
+(* --------------------------------------------------------------------- *)
+
+let lookup name bindings mv_bindings =
+ try Common.Left (List.assoc (term name) bindings)
+ with
+ Not_found ->
+ (* failure is not possible anymore *)
+ Common.Right (List.assoc (term name) mv_bindings)
+
+(* mv_bindings is for the fresh metavariables that are introduced by the
+isomorphism *)
+let instantiate bindings mv_bindings =
+ let mcode x =
+ match Ast0.get_pos x with
+ Ast0.MetaPos(name,_,_) ->
+ (try
+ match lookup name bindings mv_bindings with
+ Common.Left(Ast0.MetaPosTag(id)) -> Ast0.set_pos id x
+ | _ -> failwith "not possible"
+ with Not_found -> Ast0.set_pos Ast0.NoMetaPos x)
+ | _ -> x in
+ let donothing r k e = k e in
+
+ (* cases where metavariables can occur *)
+ let identfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaId(name,constraints,pure) ->
+ (rebuild_mcode None).V0.rebuilder_ident
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.IdentTag(id)) -> id
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaId
+ (Ast0.set_mcode_data new_mv name,constraints,pure)))
+ | Ast0.MetaFunc(name,_,pure) -> failwith "metafunc not supported"
+ | Ast0.MetaLocalFunc(name,_,pure) -> failwith "metalocalfunc not supported"
+ | _ -> e in
+
+ (* case for list metavariables *)
+ let rec elist r same_dots = function
+ [] -> []
+ | [x] ->
+ (match Ast0.unwrap x with
+ Ast0.MetaExprList(name,lenname,pure) ->
+ failwith "meta_expr_list in iso not supported"
+ (*match lookup name bindings mv_bindings with
+ Common.Left(Ast0.DotsExprTag(exp)) ->
+ (match same_dots exp with
+ Some l -> l
+ | None -> failwith "dots put in incompatible context")
+ | Common.Left(Ast0.ExprTag(exp)) -> [exp]
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ failwith "MetaExprList in SP not supported"*)
+ | _ -> [r.V0.rebuilder_expression x])
+ | x::xs -> (r.V0.rebuilder_expression x)::(elist r same_dots xs) in
+
+ let rec plist r same_dots = function
+ [] -> []
+ | [x] ->
+ (match Ast0.unwrap x with
+ Ast0.MetaParamList(name,lenname,pure) ->
+ failwith "meta_param_list in iso not supported"
+ (*match lookup name bindings mv_bindings with
+ Common.Left(Ast0.DotsParamTag(param)) ->
+ (match same_dots param with
+ Some l -> l
+ | None -> failwith "dots put in incompatible context")
+ | Common.Left(Ast0.ParamTag(param)) -> [param]
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ failwith "MetaExprList in SP not supported"*)
+ | _ -> [r.V0.rebuilder_parameter x])
+ | x::xs -> (r.V0.rebuilder_parameter x)::(plist r same_dots xs) in
+
+ let rec slist r same_dots = function
+ [] -> []
+ | [x] ->
+ (match Ast0.unwrap x with
+ Ast0.MetaStmtList(name,pure) ->
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.DotsStmtTag(stm)) ->
+ (match same_dots stm with
+ Some l -> l
+ | None -> failwith "dots put in incompatible context")
+ | Common.Left(Ast0.StmtTag(stm)) -> [stm]
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ failwith "MetaExprList in SP not supported")
+ | _ -> [r.V0.rebuilder_statement x])
+ | x::xs -> (r.V0.rebuilder_statement x)::(slist r same_dots xs) in
+
+ let same_dots d =
+ match Ast0.unwrap d with Ast0.DOTS(l) -> Some l |_ -> None in
+ let same_circles d =
+ match Ast0.unwrap d with Ast0.CIRCLES(l) -> Some l |_ -> None in
+ let same_stars d =
+ match Ast0.unwrap d with Ast0.STARS(l) -> Some l |_ -> None in
+
+ let dots list_fn r k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(list_fn r same_dots l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(list_fn r same_circles l)
+ | Ast0.STARS(l) -> Ast0.STARS(list_fn r same_stars l)) in
+
+ let exprfn r k old_e = (* need to keep the original code for ! optim *)
+ let e = k old_e in
+ let e1 =
+ match Ast0.unwrap e with
+ Ast0.MetaExpr(name,constraints,x,form,pure) ->
+ (rebuild_mcode None).V0.rebuilder_expression
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.ExprTag(exp)) -> exp
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ let new_types =
+ match x with
+ None -> None
+ | Some types ->
+ let rec renamer = function
+ Type_cocci.MetaType(name,keep,inherited) ->
+ (match
+ lookup (name,(),(),(),None) bindings mv_bindings
+ with
+ Common.Left(Ast0.TypeCTag(t)) ->
+ Ast0.ast0_type_to_type t
+ | Common.Left(_) ->
+ failwith "iso pattern: unexpected type"
+ | Common.Right(new_mv) ->
+ Type_cocci.MetaType(new_mv,keep,inherited))
+ | Type_cocci.ConstVol(cv,ty) ->
+ Type_cocci.ConstVol(cv,renamer ty)
+ | Type_cocci.Pointer(ty) ->
+ Type_cocci.Pointer(renamer ty)
+ | Type_cocci.FunctionPointer(ty) ->
+ Type_cocci.FunctionPointer(renamer ty)
+ | Type_cocci.Array(ty) ->
+ Type_cocci.Array(renamer ty)
+ | t -> t in
+ Some(List.map renamer types) in
+ Ast0.rewrap e
+ (Ast0.MetaExpr
+ (Ast0.set_mcode_data new_mv name,constraints,
+ new_types,form,pure)))
+ | Ast0.MetaErr(namea,_,pure) -> failwith "metaerr not supported"
+ | Ast0.MetaExprList(namea,lenname,pure) ->
+ failwith "metaexprlist not supported"
+ | Ast0.Unary(exp,unop) ->
+ (match Ast0.unwrap_mcode unop with
+ Ast.Not ->
+ let was_meta =
+ (* k e doesn't change the outer structure of the term,
+ only the metavars *)
+ match Ast0.unwrap old_e with
+ Ast0.Unary(exp,_) ->
+ (match Ast0.unwrap exp with
+ Ast0.MetaExpr(name,constraints,x,form,pure) -> true
+ | _ -> false)
+ | _ -> failwith "not possible" in
+ let nomodif e =
+ let mc = Ast0.get_mcodekind exp in
+ match mc with
+ Ast0.MINUS(x) ->
+ (match !x with
+ ([],_) -> true
+ | _ -> false)
+ | Ast0.CONTEXT(x) | Ast0.MIXED(x) ->
+ (match !x with
+ (Ast.NOTHING,_,_) -> true
+ | _ -> false)
+ | _ -> failwith "plus not possible" in
+ if was_meta && nomodif exp && nomodif e
+ then
+ let rec negate e (*for rewrapping*) res (*code to process*) =
+ match Ast0.unwrap res with
+ Ast0.Unary(e1,op) when Ast0.unwrap_mcode op = Ast.Not ->
+ Ast0.rewrap e (Ast0.unwrap e1)
+ | Ast0.Edots(_,_) -> Ast0.rewrap e (Ast0.unwrap res)
+ | Ast0.Paren(lp,e,rp) ->
+ Ast0.rewrap res (Ast0.Paren(lp,negate e e,rp))
+ | Ast0.Binary(e1,op,e2) ->
+ let reb nop = Ast0.rewrap_mcode op (Ast.Logical(nop)) in
+ let invop =
+ match Ast0.unwrap_mcode op with
+ Ast.Logical(Ast.Inf) ->
+ Ast0.Binary(e1,reb Ast.SupEq,e2)
+ | Ast.Logical(Ast.Sup) ->
+ Ast0.Binary(e1,reb Ast.InfEq,e2)
+ | Ast.Logical(Ast.InfEq) ->
+ Ast0.Binary(e1,reb Ast.Sup,e2)
+ | Ast.Logical(Ast.SupEq) ->
+ Ast0.Binary(e1,reb Ast.Inf,e2)
+ | Ast.Logical(Ast.Eq) ->
+ Ast0.Binary(e1,reb Ast.NotEq,e2)
+ | Ast.Logical(Ast.NotEq) ->
+ Ast0.Binary(e1,reb Ast.Eq,e2)
+ | Ast.Logical(Ast.AndLog) ->
+ Ast0.Binary(negate e1 e1,reb Ast.OrLog,
+ negate e2 e2)
+ | Ast.Logical(Ast.OrLog) ->
+ Ast0.Binary(negate e1 e1,reb Ast.AndLog,
+ negate e2 e2)
+ | _ -> Ast0.Unary(res,Ast0.rewrap_mcode op Ast.Not) in
+ Ast0.rewrap e invop
+ | Ast0.DisjExpr(lp,exps,mids,rp) ->
+ (* use res because it is the transformed argument *)
+ let exps = List.map (function e -> negate e e) exps in
+ Ast0.rewrap res (Ast0.DisjExpr(lp,exps,mids,rp))
+ | _ ->
+ (*use e, because this might be the toplevel expression*)
+ Ast0.rewrap e
+ (Ast0.Unary(res,Ast0.rewrap_mcode unop Ast.Not)) in
+ negate e exp
+ else e
+ | _ -> e)
+ | Ast0.Edots(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.ExprTag(exp) -> Ast0.rewrap e (Ast0.Edots(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | Ast0.Ecircles(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.ExprTag(exp) -> Ast0.rewrap e (Ast0.Ecircles(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | Ast0.Estars(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.ExprTag(exp) -> Ast0.rewrap e (Ast0.Estars(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | _ -> e in
+ if Ast0.get_test_exp old_e then Ast0.set_test_exp e1 else e1 in
+
+ let tyfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaType(name,pure) ->
+ (rebuild_mcode None).V0.rebuilder_typeC
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.TypeCTag(ty)) -> ty
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaType(Ast0.set_mcode_data new_mv name,pure)))
+ | _ -> e in
+
+ let declfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.Ddots(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.DeclTag(exp) -> Ast0.rewrap e (Ast0.Ddots(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | _ -> e in
+
+ let paramfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaParam(name,pure) ->
+ (rebuild_mcode None).V0.rebuilder_parameter
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.ParamTag(param)) -> param
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaParam(Ast0.set_mcode_data new_mv name, pure)))
+ | Ast0.MetaParamList(name,lenname,pure) ->
+ failwith "metaparamlist not supported"
+ | _ -> e in
+
+ let stmtfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaStmt(name,pure) ->
+ (rebuild_mcode None).V0.rebuilder_statement
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.StmtTag(stm)) -> stm
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaStmt(Ast0.set_mcode_data new_mv name,pure)))
+ | Ast0.MetaStmtList(name,pure) -> failwith "metastmtlist not supported"
+ | Ast0.Dots(d,_) ->
+ Ast0.rewrap e
+ (Ast0.Dots
+ (d,
+ List.map
+ (function (_,v) ->
+ match v with
+ Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
+ | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
+ | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
+ | _ -> failwith "unexpected binding")
+ (List.filter (function (x,v) -> x = (dot_term d)) bindings)))
+ | Ast0.Circles(d,_) ->
+ Ast0.rewrap e
+ (Ast0.Circles
+ (d,
+ List.map
+ (function (_,v) ->
+ match v with
+ Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
+ | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
+ | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
+ | _ -> failwith "unexpected binding")
+ (List.filter (function (x,v) -> x = (dot_term d)) bindings)))
+ | Ast0.Stars(d,_) ->
+ Ast0.rewrap e
+ (Ast0.Stars
+ (d,
+ List.map
+ (function (_,v) ->
+ match v with
+ Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
+ | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
+ | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
+ | _ -> failwith "unexpected binding")
+ (List.filter (function (x,v) -> x = (dot_term d)) bindings)))
+ | _ -> e in
+
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ (dots elist) donothing (dots plist) (dots slist) donothing donothing
+ identfn exprfn tyfn donothing paramfn declfn stmtfn donothing donothing
+
+(* --------------------------------------------------------------------- *)
+
+let is_minus e =
+ match Ast0.get_mcodekind e with Ast0.MINUS(cell) -> true | _ -> false
+
+let context_required e = not(is_minus e) && not !Flag.sgrep_mode2
+
+let disj_fail bindings e =
+ match bindings with
+ Some x -> Printf.fprintf stderr "no disj available at this type"; e
+ | None -> e
+
+(* isomorphism code is by default CONTEXT *)
+let merge_plus model_mcode e_mcode =
+ match model_mcode with
+ Ast0.MINUS(mc) ->
+ (* add the replacement information at the root *)
+ (match e_mcode with
+ Ast0.MINUS(emc) ->
+ emc :=
+ (match (!mc,!emc) with
+ (([],_),(x,t)) | ((x,_),([],t)) -> (x,t)
+ | _ -> failwith "how can we combine minuses?")
+ | _ -> failwith "not possible 6")
+ | Ast0.CONTEXT(mc) ->
+ (match e_mcode with
+ Ast0.CONTEXT(emc) ->
+ (* keep the logical line info as in the model *)
+ let (mba,tb,ta) = !mc in
+ let (eba,_,_) = !emc in
+ (* merging may be required when a term is replaced by a subterm *)
+ let merged =
+ match (mba,eba) with
+ (x,Ast.NOTHING) | (Ast.NOTHING,x) -> x
+ | (Ast.BEFORE(b1),Ast.BEFORE(b2)) -> Ast.BEFORE(b1@b2)
+ | (Ast.BEFORE(b),Ast.AFTER(a)) -> Ast.BEFOREAFTER(b,a)
+ | (Ast.BEFORE(b1),Ast.BEFOREAFTER(b2,a)) ->
+ Ast.BEFOREAFTER(b1@b2,a)
+ | (Ast.AFTER(a),Ast.BEFORE(b)) -> Ast.BEFOREAFTER(b,a)
+ | (Ast.AFTER(a1),Ast.AFTER(a2)) ->Ast.AFTER(a2@a1)
+ | (Ast.AFTER(a1),Ast.BEFOREAFTER(b,a2)) -> Ast.BEFOREAFTER(b,a2@a1)
+ | (Ast.BEFOREAFTER(b1,a),Ast.BEFORE(b2)) ->
+ Ast.BEFOREAFTER(b1@b2,a)
+ | (Ast.BEFOREAFTER(b,a1),Ast.AFTER(a2)) ->
+ Ast.BEFOREAFTER(b,a2@a1)
+ | (Ast.BEFOREAFTER(b1,a1),Ast.BEFOREAFTER(b2,a2)) ->
+ Ast.BEFOREAFTER(b1@b2,a2@a1) in
+ emc := (merged,tb,ta)
+ | Ast0.MINUS(emc) ->
+ let (anything_bef_aft,_,_) = !mc in
+ let (anythings,t) = !emc in
+ emc :=
+ (match anything_bef_aft with
+ Ast.BEFORE(b) -> (b@anythings,t)
+ | Ast.AFTER(a) -> (anythings@a,t)
+ | Ast.BEFOREAFTER(b,a) -> (b@anythings@a,t)
+ | Ast.NOTHING -> (anythings,t))
+ | _ -> failwith "not possible 7")
+ | Ast0.MIXED(_) -> failwith "not possible 8"
+ | Ast0.PLUS -> failwith "not possible 9"
+
+let copy_plus printer minusify model e =
+ if !Flag.sgrep_mode2
+ then e (* no plus code, can cause a "not possible" error, so just avoid it *)
+ else
+ let e =
+ match Ast0.get_mcodekind model with
+ Ast0.MINUS(mc) -> minusify e
+ | Ast0.CONTEXT(mc) -> e
+ | _ -> failwith "not possible: copy_plus\n" in
+ merge_plus (Ast0.get_mcodekind model) (Ast0.get_mcodekind e);
+ e
+
+let copy_minus printer minusify model e =
+ match Ast0.get_mcodekind model with
+ Ast0.MINUS(mc) -> minusify e
+ | Ast0.CONTEXT(mc) -> e
+ | Ast0.MIXED(_) ->
+ if !Flag.sgrep_mode2
+ then e
+ else failwith "not possible 8"
+ | Ast0.PLUS -> failwith "not possible 9"
+
+let whencode_allowed prev_ecount prev_icount prev_dcount
+ ecount icount dcount rest =
+ (* actually, if ecount or dcount is 0, the flag doesn't matter, because it
+ won't be tested *)
+ let other_ecount = (* number of edots *)
+ List.fold_left (function rest -> function (_,ec,ic,dc) -> ec + rest)
+ prev_ecount rest in
+ let other_icount = (* number of dots *)
+ List.fold_left (function rest -> function (_,ec,ic,dc) -> ic + rest)
+ prev_icount rest in
+ let other_dcount = (* number of dots *)
+ List.fold_left (function rest -> function (_,ec,ic,dc) -> dc + rest)
+ prev_dcount rest in
+ (ecount = 0 or other_ecount = 0, icount = 0 or other_icount = 0,
+ dcount = 0 or other_dcount = 0)
+
+(* copy the befores and afters to the instantiated code *)
+let extra_copy_stmt_plus model e =
+ (if not !Flag.sgrep_mode2 (* sgrep has no plus code, so nothing to do *)
+ then
+ (match Ast0.unwrap model with
+ Ast0.FunDecl((info,bef),_,_,_,_,_,_,_,_)
+ | Ast0.Decl((info,bef),_) ->
+ (match Ast0.unwrap e with
+ Ast0.FunDecl((info,bef1),_,_,_,_,_,_,_,_)
+ | Ast0.Decl((info,bef1),_) ->
+ merge_plus bef bef1
+ | _ -> merge_plus bef (Ast0.get_mcodekind e))
+ | Ast0.IfThen(_,_,_,_,_,(info,aft))
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft))
+ | Ast0.While(_,_,_,_,_,(info,aft))
+ | Ast0.For(_,_,_,_,_,_,_,_,_,(info,aft))
+ | Ast0.Iterator(_,_,_,_,_,(info,aft)) ->
+ (match Ast0.unwrap e with
+ Ast0.IfThen(_,_,_,_,_,(info,aft1))
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft1))
+ | Ast0.While(_,_,_,_,_,(info,aft1))
+ | Ast0.For(_,_,_,_,_,_,_,_,_,(info,aft1))
+ | Ast0.Iterator(_,_,_,_,_,(info,aft1)) ->
+ merge_plus aft aft1
+ | _ -> merge_plus aft (Ast0.get_mcodekind e))
+ | _ -> ()));
+ e
+
+let extra_copy_other_plus model e = e
+
+(* --------------------------------------------------------------------- *)
+
+let mv_count = ref 0
+let new_mv (_,s) =
+ let ct = !mv_count in
+ mv_count := !mv_count + 1;
+ "_"^s^"_"^(string_of_int ct)
+
+let get_name = function
+ Ast.MetaIdDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaIdDecl(ar,nm))
+ | Ast.MetaFreshIdDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaFreshIdDecl(ar,nm))
+ | Ast.MetaTypeDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaTypeDecl(ar,nm))
+ | Ast.MetaListlenDecl(nm) ->
+ failwith "should not be rebuilt"
+ | Ast.MetaParamDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaParamDecl(ar,nm))
+ | Ast.MetaParamListDecl(ar,nm,nm1) ->
+ (nm,function nm -> Ast.MetaParamListDecl(ar,nm,nm1))
+ | Ast.MetaConstDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaConstDecl(ar,nm,ty))
+ | Ast.MetaErrDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaErrDecl(ar,nm))
+ | Ast.MetaExpDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaExpDecl(ar,nm,ty))
+ | Ast.MetaIdExpDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaIdExpDecl(ar,nm,ty))
+ | Ast.MetaLocalIdExpDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaLocalIdExpDecl(ar,nm,ty))
+ | Ast.MetaExpListDecl(ar,nm,nm1) ->
+ (nm,function nm -> Ast.MetaExpListDecl(ar,nm,nm1))
+ | Ast.MetaStmDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaStmDecl(ar,nm))
+ | Ast.MetaStmListDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaStmListDecl(ar,nm))
+ | Ast.MetaFuncDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaFuncDecl(ar,nm))
+ | Ast.MetaLocalFuncDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaLocalFuncDecl(ar,nm))
+ | Ast.MetaPosDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaPosDecl(ar,nm))
+ | Ast.MetaDeclarerDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaDeclarerDecl(ar,nm))
+ | Ast.MetaIteratorDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaIteratorDecl(ar,nm))
+
+let make_new_metavars metavars bindings =
+ let new_metavars =
+ List.filter
+ (function mv ->
+ let (s,_) = get_name mv in
+ try let _ = List.assoc s bindings in false with Not_found -> true)
+ metavars in
+ List.split
+ (List.map
+ (function mv ->
+ let (s,rebuild) = get_name mv in
+ let new_s = (!current_rule,new_mv s) in
+ (rebuild new_s, (s,new_s)))
+ new_metavars)
+
+(* --------------------------------------------------------------------- *)
+
+let do_nothing x = x
+
+let mkdisj matcher metavars alts e instantiater mkiso disj_maker minusify
+ rebuild_mcodes name printer extra_plus update_others =
+ let call_instantiate bindings mv_bindings alts =
+ List.concat
+ (List.map
+ (function (a,_,_,_) ->
+ nub
+ (* no need to create duplicates when the bindings have no effect *)
+ (List.map
+ (function bindings ->
+ Ast0.set_iso
+ (copy_plus printer minusify e
+ (extra_plus e
+ (instantiater bindings mv_bindings
+ (rebuild_mcodes a))))
+ (Common.union_set [(name,mkiso a)] (Ast0.get_iso e)))
+ bindings))
+ alts) in
+ let rec inner_loop all_alts prev_ecount prev_icount prev_dcount = function
+ [] -> Common.Left (prev_ecount, prev_icount, prev_dcount)
+ | ((pattern,ecount,icount,dcount)::rest) ->
+ let wc =
+ whencode_allowed prev_ecount prev_icount prev_dcount
+ ecount dcount icount rest in
+ (match matcher true (context_required e) wc pattern e init_env with
+ Fail(reason) ->
+ if reason = NonMatch || not !Flag_parsing_cocci.show_iso_failures
+ then ()
+ else
+ (match matcher false false wc pattern e init_env with
+ OK _ ->
+ interpret_reason name (Ast0.get_line e) reason
+ (function () -> printer e)
+ | _ -> ());
+ inner_loop all_alts (prev_ecount + ecount) (prev_icount + icount)
+ (prev_dcount + dcount) rest
+ | OK (bindings : (((string * string) * 'a) list list)) ->
+ let all_alts =
+ (* apply update_others to all patterns other than the matched
+ one. This is used to desigate the others as test
+ expressions in the TestExpression case *)
+ (List.map
+ (function (x,e,i,d) as all ->
+ if x = pattern
+ then all
+ else (update_others x,e,i,d))
+ (List.hd all_alts)) ::
+ (List.map
+ (List.map (function (x,e,i,d) -> (update_others x,e,i,d)))
+ (List.tl all_alts)) in
+ (match List.concat all_alts with
+ [x] -> Common.Left (prev_ecount, prev_icount, prev_dcount)
+ | all_alts ->
+ let (new_metavars,mv_bindings) =
+ make_new_metavars metavars (nub(List.concat bindings)) in
+ Common.Right
+ (new_metavars,
+ call_instantiate bindings mv_bindings all_alts))) in
+ let rec outer_loop prev_ecount prev_icount prev_dcount = function
+ [] | [[_]] (*only one alternative*) -> ([],e) (* nothing matched *)
+ | (alts::rest) as all_alts ->
+ match inner_loop all_alts prev_ecount prev_icount prev_dcount alts with
+ Common.Left(prev_ecount, prev_icount, prev_dcount) ->
+ outer_loop prev_ecount prev_icount prev_dcount rest
+ | Common.Right (new_metavars,res) ->
+ (new_metavars,
+ copy_minus printer minusify e (disj_maker res)) in
+ outer_loop 0 0 0 alts
+
+(* no one should ever look at the information stored in these mcodes *)
+let disj_starter lst =
+ let old_info = Ast0.get_info(List.hd lst) in
+ let info =
+ { old_info with
+ Ast0.line_end = old_info.Ast0.line_start;
+ Ast0.logical_end = old_info.Ast0.logical_start;
+ Ast0.attachable_start = false; Ast0.attachable_end = false;
+ Ast0.mcode_start = []; Ast0.mcode_end = [];
+ Ast0.strings_before = []; Ast0.strings_after = [] } in
+ Ast0.make_mcode_info "(" info
+
+let disj_ender lst =
+ let old_info = Ast0.get_info(List.hd lst) in
+ let info =
+ { old_info with
+ Ast0.line_start = old_info.Ast0.line_end;
+ Ast0.logical_start = old_info.Ast0.logical_end;
+ Ast0.attachable_start = false; Ast0.attachable_end = false;
+ Ast0.mcode_start = []; Ast0.mcode_end = [];
+ Ast0.strings_before = []; Ast0.strings_after = [] } in
+ Ast0.make_mcode_info ")" info
+
+let disj_mid _ = Ast0.make_mcode "|"
+
+let make_disj_type tl =
+ let mids =
+ match tl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap (Ast0.DisjType(disj_starter tl,tl,mids,disj_ender tl))
+let make_disj_stmt_list tl =
+ let mids =
+ match tl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap (Ast0.Disj(disj_starter tl,tl,mids,disj_ender tl))
+let make_disj_expr model el =
+ let mids =
+ match el with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ let update_arg x =
+ if Ast0.get_arg_exp model then Ast0.set_arg_exp x else x in
+ let update_test x =
+ let x = if Ast0.get_test_pos model then Ast0.set_test_pos x else x in
+ if Ast0.get_test_exp model then Ast0.set_test_exp x else x in
+ let el = List.map update_arg (List.map update_test el) in
+ Ast0.context_wrap (Ast0.DisjExpr(disj_starter el,el,mids,disj_ender el))
+let make_disj_decl dl =
+ let mids =
+ match dl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap (Ast0.DisjDecl(disj_starter dl,dl,mids,disj_ender dl))
+let make_disj_stmt sl =
+ let dotify x = Ast0.context_wrap (Ast0.DOTS[x]) in
+ let mids =
+ match sl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap
+ (Ast0.Disj(disj_starter sl,List.map dotify sl,mids,disj_ender sl))
+
+let transform_type (metavars,alts,name) e =
+ match alts with
+ (Ast0.TypeCTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some ((Ast0.get_info e).Ast0.line_start) in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.TypeCTag(p) ->
+ (p,count_edots.V0.combiner_typeC p,
+ count_idots.V0.combiner_typeC p,
+ count_dots.V0.combiner_typeC p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_typeC metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_typeC)
+ (function t -> Ast0.TypeCTag t)
+ make_disj_type make_minus.V0.rebuilder_typeC
+ (rebuild_mcode start_line).V0.rebuilder_typeC
+ name Unparse_ast0.typeC extra_copy_other_plus do_nothing
+ | _ -> ([],e)
+
+
+let transform_expr (metavars,alts,name) e =
+ let process update_others =
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some ((Ast0.get_info e).Ast0.line_start) in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.ExprTag(p) | Ast0.ArgExprTag(p) | Ast0.TestExprTag(p) ->
+ (p,count_edots.V0.combiner_expression p,
+ count_idots.V0.combiner_expression p,
+ count_dots.V0.combiner_expression p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_expr metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_expression)
+ (function e -> Ast0.ExprTag e)
+ (make_disj_expr e) make_minus.V0.rebuilder_expression
+ (rebuild_mcode start_line).V0.rebuilder_expression
+ name Unparse_ast0.expression extra_copy_other_plus update_others in
+ match alts with
+ (Ast0.ExprTag(_)::_)::_ -> process do_nothing
+ | (Ast0.ArgExprTag(_)::_)::_ when Ast0.get_arg_exp e -> process do_nothing
+ | (Ast0.TestExprTag(_)::_)::_ when Ast0.get_test_pos e ->
+ process Ast0.set_test_exp
+ | _ -> ([],e)
+
+let transform_decl (metavars,alts,name) e =
+ match alts with
+ (Ast0.DeclTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some (Ast0.get_info e).Ast0.line_start in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.DeclTag(p) ->
+ (p,count_edots.V0.combiner_declaration p,
+ count_idots.V0.combiner_declaration p,
+ count_dots.V0.combiner_declaration p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_decl metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_declaration)
+ (function d -> Ast0.DeclTag d)
+ make_disj_decl
+ make_minus.V0.rebuilder_declaration
+ (rebuild_mcode start_line).V0.rebuilder_declaration
+ name Unparse_ast0.declaration extra_copy_other_plus do_nothing
+ | _ -> ([],e)
+
+let transform_stmt (metavars,alts,name) e =
+ match alts with
+ (Ast0.StmtTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some (Ast0.get_info e).Ast0.line_start in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.StmtTag(p) ->
+ (p,count_edots.V0.combiner_statement p,
+ count_idots.V0.combiner_statement p,
+ count_dots.V0.combiner_statement p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_statement metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_statement)
+ (function s -> Ast0.StmtTag s)
+ make_disj_stmt make_minus.V0.rebuilder_statement
+ (rebuild_mcode start_line).V0.rebuilder_statement
+ name (Unparse_ast0.statement "") extra_copy_stmt_plus do_nothing
+ | _ -> ([],e)
+
+(* sort of a hack, because there is no disj at top level *)
+let transform_top (metavars,alts,name) e =
+ match Ast0.unwrap e with
+ Ast0.DECL(declstm) ->
+ (try
+ let strip alts =
+ List.map
+ (List.map
+ (function
+ Ast0.DotsStmtTag(d) ->
+ (match Ast0.unwrap d with
+ Ast0.DOTS([s]) -> Ast0.StmtTag(s)
+ | _ -> raise (Failure ""))
+ | _ -> raise (Failure "")))
+ alts in
+ let (mv,s) = transform_stmt (metavars,strip alts,name) declstm in
+ (mv,Ast0.rewrap e (Ast0.DECL(s)))
+ with Failure _ -> ([],e))
+ | Ast0.CODE(stmts) ->
+ let (mv,res) =
+ match alts with
+ (Ast0.DotsStmtTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some ((Ast0.get_info e).Ast0.line_start) in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.DotsStmtTag(p) ->
+ (p,count_edots.V0.combiner_statement_dots p,
+ count_idots.V0.combiner_statement_dots p,
+ count_dots.V0.combiner_statement_dots p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_statement_dots metavars alts stmts
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_statement_dots)
+ (function s -> Ast0.DotsStmtTag s)
+ (function x ->
+ Ast0.rewrap e (Ast0.DOTS([make_disj_stmt_list x])))
+ make_minus.V0.rebuilder_statement_dots
+ (rebuild_mcode start_line).V0.rebuilder_statement_dots
+ name Unparse_ast0.statement_dots extra_copy_other_plus do_nothing
+ | _ -> ([],stmts) in
+ (mv,Ast0.rewrap e (Ast0.CODE res))
+ | _ -> ([],e)
+
+(* --------------------------------------------------------------------- *)
+
+let transform (alts : isomorphism) t =
+ (* the following ugliness is because rebuilder only returns a new term *)
+ let extra_meta_decls = ref ([] : Ast_cocci.metavar list) in
+ let mcode x = x in
+ let donothing r k e = k e in
+ let exprfn r k e =
+ let (extra_meta,exp) = transform_expr alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ exp in
+
+ let declfn r k e =
+ let (extra_meta,dec) = transform_decl alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ dec in
+
+ let stmtfn r k e =
+ let (extra_meta,stm) = transform_stmt alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ stm in
+
+ let typefn r k e =
+ let (extra_meta,ty) = transform_type alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ ty in
+
+ let topfn r k e =
+ let (extra_meta,ty) = transform_top alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ ty in
+
+ let res =
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing exprfn typefn donothing donothing declfn stmtfn
+ donothing topfn in
+ let res = res.V0.rebuilder_top_level t in
+ (!extra_meta_decls,res)
+
+(* --------------------------------------------------------------------- *)
+
+(* should be done by functorizing the parser to use wrap or context_wrap *)
+let rewrap =
+ let mcode (x,a,i,mc,pos) = (x,a,i,Ast0.context_befaft(),pos) in
+ let donothing r k e = Ast0.context_wrap(Ast0.unwrap(k e)) in
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing
+
+let rewrap_anything = function
+ Ast0.DotsExprTag(d) ->
+ Ast0.DotsExprTag(rewrap.V0.rebuilder_expression_dots d)
+ | Ast0.DotsInitTag(d) ->
+ Ast0.DotsInitTag(rewrap.V0.rebuilder_initialiser_list d)
+ | Ast0.DotsParamTag(d) ->
+ Ast0.DotsParamTag(rewrap.V0.rebuilder_parameter_list d)
+ | Ast0.DotsStmtTag(d) ->
+ Ast0.DotsStmtTag(rewrap.V0.rebuilder_statement_dots d)
+ | Ast0.DotsDeclTag(d) ->
+ Ast0.DotsDeclTag(rewrap.V0.rebuilder_declaration_dots d)
+ | Ast0.DotsCaseTag(d) ->
+ Ast0.DotsCaseTag(rewrap.V0.rebuilder_case_line_dots d)
+ | Ast0.IdentTag(d) -> Ast0.IdentTag(rewrap.V0.rebuilder_ident d)
+ | Ast0.ExprTag(d) -> Ast0.ExprTag(rewrap.V0.rebuilder_expression d)
+ | Ast0.ArgExprTag(d) -> Ast0.ArgExprTag(rewrap.V0.rebuilder_expression d)
+ | Ast0.TestExprTag(d) -> Ast0.TestExprTag(rewrap.V0.rebuilder_expression d)
+ | Ast0.TypeCTag(d) -> Ast0.TypeCTag(rewrap.V0.rebuilder_typeC d)
+ | Ast0.InitTag(d) -> Ast0.InitTag(rewrap.V0.rebuilder_initialiser d)
+ | Ast0.ParamTag(d) -> Ast0.ParamTag(rewrap.V0.rebuilder_parameter d)
+ | Ast0.DeclTag(d) -> Ast0.DeclTag(rewrap.V0.rebuilder_declaration d)
+ | Ast0.StmtTag(d) -> Ast0.StmtTag(rewrap.V0.rebuilder_statement d)
+ | Ast0.CaseLineTag(d) -> Ast0.CaseLineTag(rewrap.V0.rebuilder_case_line d)
+ | Ast0.TopTag(d) -> Ast0.TopTag(rewrap.V0.rebuilder_top_level d)
+ | Ast0.IsoWhenTag(_) -> failwith "only for isos within iso phase"
+ | Ast0.MetaPosTag(p) -> Ast0.MetaPosTag(p)
+
+(* --------------------------------------------------------------------- *)
+
+let apply_isos isos rule rule_name =
+ if isos = []
+ then ([],rule)
+ else
+ begin
+ current_rule := rule_name;
+ let isos =
+ List.map
+ (function (metavars,iso,name) ->
+ (metavars,List.map (List.map rewrap_anything) iso,name))
+ isos in
+ let (extra_meta,rule) =
+ List.split
+ (List.map
+ (function t ->
+ List.fold_left
+ (function (extra_meta,t) -> function iso ->
+ let (new_extra_meta,t) = transform iso t in
+ (new_extra_meta@extra_meta,t))
+ ([],t) isos)
+ rule) in
+ (List.concat extra_meta, Compute_lines.compute_lines rule)
+ end
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* Potential problem: offset of mcode is not updated when an iso is
+instantiated, implying that a term may end up with many mcodes with the
+same offset. On the other hand, at the moment offset only seems to be used
+before this phase. Furthermore add_dot_binding relies on the offset to
+remain the same between matching an iso and instantiating it with bindings. *)
+
+(* --------------------------------------------------------------------- *)
+(* match a SmPL expression against a SmPL abstract syntax tree,
+either - or + *)
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+
+let current_rule = ref ""
+
+(* --------------------------------------------------------------------- *)
+
+type isomorphism =
+ Ast_cocci.metavar list * Ast0_cocci.anything list list * string (* name *)
+
+let strip_info =
+ let mcode (term,_,_,_,_) =
+ (term,Ast0.NONE,Ast0.default_info(),Ast0.PLUS,ref Ast0.NoMetaPos) in
+ let donothing r k e =
+ let x = k e in
+ {(Ast0.wrap (Ast0.unwrap x)) with
+ Ast0.mcodekind = ref Ast0.PLUS;
+ Ast0.true_if_test = x.Ast0.true_if_test} in
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing
+
+let anything_equal = function
+ (Ast0.DotsExprTag(d1),Ast0.DotsExprTag(d2)) ->
+ failwith "not a possible variable binding" (*not sure why these are pbs*)
+ | (Ast0.DotsInitTag(d1),Ast0.DotsInitTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.DotsParamTag(d1),Ast0.DotsParamTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.DotsStmtTag(d1),Ast0.DotsStmtTag(d2)) ->
+ (strip_info.V0.rebuilder_statement_dots d1) =
+ (strip_info.V0.rebuilder_statement_dots d2)
+ | (Ast0.DotsDeclTag(d1),Ast0.DotsDeclTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.DotsCaseTag(d1),Ast0.DotsCaseTag(d2)) ->
+ failwith "not a possible variable binding"
+ | (Ast0.IdentTag(d1),Ast0.IdentTag(d2)) ->
+ (strip_info.V0.rebuilder_ident d1) = (strip_info.V0.rebuilder_ident d2)
+ | (Ast0.ExprTag(d1),Ast0.ExprTag(d2)) ->
+ (strip_info.V0.rebuilder_expression d1) =
+ (strip_info.V0.rebuilder_expression d2)
+ | (Ast0.ArgExprTag(_),_) | (_,Ast0.ArgExprTag(_)) ->
+ failwith "not possible - only in isos1"
+ | (Ast0.TestExprTag(_),_) | (_,Ast0.TestExprTag(_)) ->
+ failwith "not possible - only in isos1"
+ | (Ast0.TypeCTag(d1),Ast0.TypeCTag(d2)) ->
+ (strip_info.V0.rebuilder_typeC d1) =
+ (strip_info.V0.rebuilder_typeC d2)
+ | (Ast0.InitTag(d1),Ast0.InitTag(d2)) ->
+ (strip_info.V0.rebuilder_initialiser d1) =
+ (strip_info.V0.rebuilder_initialiser d2)
+ | (Ast0.ParamTag(d1),Ast0.ParamTag(d2)) ->
+ (strip_info.V0.rebuilder_parameter d1) =
+ (strip_info.V0.rebuilder_parameter d2)
+ | (Ast0.DeclTag(d1),Ast0.DeclTag(d2)) ->
+ (strip_info.V0.rebuilder_declaration d1) =
+ (strip_info.V0.rebuilder_declaration d2)
+ | (Ast0.StmtTag(d1),Ast0.StmtTag(d2)) ->
+ (strip_info.V0.rebuilder_statement d1) =
+ (strip_info.V0.rebuilder_statement d2)
+ | (Ast0.CaseLineTag(d1),Ast0.CaseLineTag(d2)) ->
+ (strip_info.V0.rebuilder_case_line d1) =
+ (strip_info.V0.rebuilder_case_line d2)
+ | (Ast0.TopTag(d1),Ast0.TopTag(d2)) ->
+ (strip_info.V0.rebuilder_top_level d1) =
+ (strip_info.V0.rebuilder_top_level d2)
+ | (Ast0.IsoWhenTTag(_),_) | (_,Ast0.IsoWhenTTag(_)) ->
+ failwith "only for isos within iso phase"
+ | (Ast0.IsoWhenFTag(_),_) | (_,Ast0.IsoWhenFTag(_)) ->
+ failwith "only for isos within iso phase"
+ | (Ast0.IsoWhenTag(_),_) | (_,Ast0.IsoWhenTag(_)) ->
+ failwith "only for isos within iso phase"
+ | _ -> false
+
+let term (var1,_,_,_,_) = var1
+let dot_term (var1,_,info,_,_) = ("", var1 ^ (string_of_int info.Ast0.offset))
+
+
+type reason =
+ NotPure of Ast0.pure * (string * string) * Ast0.anything
+ | NotPureLength of (string * string)
+ | ContextRequired of Ast0.anything
+ | NonMatch
+ | Braces of Ast0.statement
+ | Position of string * string
+
+let interpret_reason name line reason printer =
+ Printf.printf
+ "warning: iso %s does not match the code below on line %d\n" name line;
+ printer(); Format.print_newline();
+ match reason with
+ NotPure(Ast0.Pure,(_,var),nonpure) ->
+ Printf.printf
+ "pure metavariable %s is matched against the following nonpure code:\n"
+ var;
+ Unparse_ast0.unparse_anything nonpure
+ | NotPure(Ast0.Context,(_,var),nonpure) ->
+ Printf.printf
+ "context metavariable %s is matched against the following\nnoncontext code:\n"
+ var;
+ Unparse_ast0.unparse_anything nonpure
+ | NotPure(Ast0.PureContext,(_,var),nonpure) ->
+ Printf.printf
+ "pure context metavariable %s is matched against the following\nnonpure or noncontext code:\n"
+ var;
+ Unparse_ast0.unparse_anything nonpure
+ | NotPureLength((_,var)) ->
+ Printf.printf
+ "pure metavariable %s is matched against too much or too little code\n"
+ var;
+ | ContextRequired(term) ->
+ Printf.printf
+ "the following code matched is not uniformly minus or context,\nor contains a disjunction:\n";
+ Unparse_ast0.unparse_anything term
+ | Braces(s) ->
+ Printf.printf "braces must be all minus (plus code allowed) or all\ncontext (plus code not allowed in the body) to match:\n";
+ Unparse_ast0.statement "" s;
+ Format.print_newline()
+ | Position(rule,name) ->
+ Printf.printf "position variable %s.%s conflicts with an isomorphism\n"
+ rule name;
+ | _ -> failwith "not possible"
+
+type 'a either = OK of 'a | Fail of reason
+
+let add_binding var exp bindings =
+ let var = term var in
+ let attempt bindings =
+ try
+ let cur = List.assoc var bindings in
+ if anything_equal(exp,cur) then [bindings] else []
+ with Not_found -> [((var,exp)::bindings)] in
+ match List.concat(List.map attempt bindings) with
+ [] -> Fail NonMatch
+ | x -> OK x
+
+let add_dot_binding var exp bindings =
+ let var = dot_term var in
+ let attempt bindings =
+ try
+ let cur = List.assoc var bindings in
+ if anything_equal(exp,cur) then [bindings] else []
+ with Not_found -> [((var,exp)::bindings)] in
+ match List.concat(List.map attempt bindings) with
+ [] -> Fail NonMatch
+ | x -> OK x
+
+(* multi-valued *)
+let add_multi_dot_binding var exp bindings =
+ let var = dot_term var in
+ let attempt bindings = [((var,exp)::bindings)] in
+ match List.concat(List.map attempt bindings) with
+ [] -> Fail NonMatch
+ | x -> OK x
+
+let rec nub ls =
+ match ls with
+ [] -> []
+ | (x::xs) when (List.mem x xs) -> nub xs
+ | (x::xs) -> x::(nub xs)
+
+(* --------------------------------------------------------------------- *)
+
+let init_env = [[]]
+
+let debug str m binding =
+ let res = m binding in
+ (match res with
+ None -> Printf.printf "%s: failed\n" str
+ | Some binding ->
+ List.iter
+ (function binding ->
+ Printf.printf "%s: %s\n" str
+ (String.concat " " (List.map (function (x,_) -> x) binding)))
+ binding);
+ res
+
+let conjunct_bindings
+ (m1 : 'binding -> 'binding either)
+ (m2 : 'binding -> 'binding either)
+ (binding : 'binding) : 'binding either =
+ match m1 binding with Fail(reason) -> Fail(reason) | OK binding -> m2 binding
+
+let rec conjunct_many_bindings = function
+ [] -> failwith "not possible"
+ | [x] -> x
+ | x::xs -> conjunct_bindings x (conjunct_many_bindings xs)
+
+let mcode_equal (x,_,_,_,_) (y,_,_,_,_) = x = y
+
+let return b binding = if b then OK binding else Fail NonMatch
+let return_false reason binding = Fail reason
+
+let match_option f t1 t2 =
+ match (t1,t2) with
+ (Some t1, Some t2) -> f t1 t2
+ | (None, None) -> return true
+ | _ -> return false
+
+let bool_match_option f t1 t2 =
+ match (t1,t2) with
+ (Some t1, Some t2) -> f t1 t2
+ | (None, None) -> true
+ | _ -> false
+
+(* context_required is for the example
+ if (
++ (int * )
+ x == NULL)
+ where we can't change x == NULL to eg NULL == x. So there can either be
+ nothing attached to the root or the term has to be all removed.
+ if would be nice if we knew more about the relationship between the - and +
+ code, because in the case where the + code is a separate statement in a
+ sequence, this is not a problem. Perhaps something could be done in
+ insert_plus
+
+ The example seems strange. Why isn't the cast attached to x?
+ *)
+let is_context e =
+ !Flag.sgrep_mode2 or (* everything is context for sgrep *)
+ (match Ast0.get_mcodekind e with
+ Ast0.CONTEXT(cell) -> true
+ | _ -> false)
+
+(* needs a special case when there is a Disj or an empty DOTS
+ the following stops at the statement level, and gives true if one
+ statement is replaced by another *)
+let rec is_pure_context s =
+ !Flag.sgrep_mode2 or (* everything is context for sgrep *)
+ (match Ast0.unwrap s with
+ Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ List.for_all
+ (function x ->
+ match Ast0.undots x with
+ [s] -> is_pure_context s
+ | _ -> false (* could we do better? *))
+ statement_dots_list
+ | _ ->
+ (match Ast0.get_mcodekind s with
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) -> true
+ | _ -> false)
+ | Ast0.MINUS(mc) ->
+ (match !mc with
+ (* do better for the common case of replacing a stmt by another one *)
+ ([[Ast.StatementTag(s)]],_) ->
+ (match Ast.unwrap s with
+ Ast.IfThen(_,_,_) -> false (* potentially dangerous *)
+ | _ -> true)
+ | (_,_) -> false)
+ | _ -> false))
+
+let is_minus e =
+ match Ast0.get_mcodekind e with Ast0.MINUS(cell) -> true | _ -> false
+
+let match_list matcher is_list_matcher do_list_match la lb =
+ let rec loop = function
+ ([],[]) -> return true
+ | ([x],lb) when is_list_matcher x -> do_list_match x lb
+ | (x::xs,y::ys) -> conjunct_bindings (matcher x y) (loop (xs,ys))
+ | _ -> return false in
+ loop (la,lb)
+
+let match_maker checks_needed context_required whencode_allowed =
+
+ let check_mcode pmc cmc binding =
+ if checks_needed
+ then
+ match Ast0.get_pos cmc with
+ (Ast0.MetaPos (name,_,_)) as x ->
+ (match Ast0.get_pos pmc with
+ Ast0.MetaPos (name1,_,_) ->
+ add_binding name1 (Ast0.MetaPosTag x) binding
+ | Ast0.NoMetaPos ->
+ let (rule,name) = Ast0.unwrap_mcode name in
+ Fail (Position(rule,name)))
+ | Ast0.NoMetaPos -> OK binding
+ else OK binding in
+
+ let match_dots matcher is_list_matcher do_list_match d1 d2 =
+ match (Ast0.unwrap d1, Ast0.unwrap d2) with
+ (Ast0.DOTS(la),Ast0.DOTS(lb))
+ | (Ast0.CIRCLES(la),Ast0.CIRCLES(lb))
+ | (Ast0.STARS(la),Ast0.STARS(lb)) ->
+ match_list matcher is_list_matcher (do_list_match d2) la lb
+ | _ -> return false in
+
+ let is_elist_matcher el =
+ match Ast0.unwrap el with Ast0.MetaExprList(_,_,_) -> true | _ -> false in
+
+ let is_plist_matcher pl =
+ match Ast0.unwrap pl with Ast0.MetaParamList(_,_,_) -> true | _ -> false in
+
+ let is_slist_matcher pl =
+ match Ast0.unwrap pl with Ast0.MetaStmtList(_,_) -> true | _ -> false in
+
+ let no_list _ = false in
+
+ let build_dots pattern data =
+ match Ast0.unwrap pattern with
+ Ast0.DOTS(_) -> Ast0.rewrap pattern (Ast0.DOTS(data))
+ | Ast0.CIRCLES(_) -> Ast0.rewrap pattern (Ast0.CIRCLES(data))
+ | Ast0.STARS(_) -> Ast0.rewrap pattern (Ast0.STARS(data)) in
+
+ let pure_sp_code =
+ let bind = Ast0.lub_pure in
+ let option_default = Ast0.Context in
+ let pure_mcodekind = function
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) -> Ast0.PureContext
+ | _ -> Ast0.Context)
+ | Ast0.MINUS(mc) ->
+ (match !mc with ([],_) -> Ast0.Pure | _ -> Ast0.Impure)
+ | _ -> Ast0.Impure in
+ let donothing r k e =
+ bind (pure_mcodekind (Ast0.get_mcodekind e)) (k e) in
+
+ let mcode m = pure_mcodekind (Ast0.get_mcode_mcodekind m) in
+
+ (* a case for everything that has a metavariable *)
+ (* pure is supposed to match only unitary metavars, not anything that
+ contains only unitary metavars *)
+ let ident r k i =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind i)) (k i))
+ (match Ast0.unwrap i with
+ Ast0.MetaId(name,_,pure) | Ast0.MetaFunc(name,_,pure)
+ | Ast0.MetaLocalFunc(name,_,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ let expression r k e =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind e)) (k e))
+ (match Ast0.unwrap e with
+ Ast0.MetaErr(name,_,pure)
+ | Ast0.MetaExpr(name,_,_,_,pure) | Ast0.MetaExprList(name,_,pure) ->
+ pure
+ | _ -> Ast0.Impure) in
+
+ let typeC r k t =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind t)) (k t))
+ (match Ast0.unwrap t with
+ Ast0.MetaType(name,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ let param r k p =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind p)) (k p))
+ (match Ast0.unwrap p with
+ Ast0.MetaParam(name,pure) | Ast0.MetaParamList(name,_,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ let stmt r k s =
+ bind (bind (pure_mcodekind (Ast0.get_mcodekind s)) (k s))
+ (match Ast0.unwrap s with
+ Ast0.MetaStmt(name,pure) | Ast0.MetaStmtList(name,pure) -> pure
+ | _ -> Ast0.Impure) in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ ident expression typeC donothing param donothing stmt donothing
+ donothing in
+
+ let add_pure_list_binding name pure is_pure builder1 builder2 lst =
+ match (checks_needed,pure) with
+ (true,Ast0.Pure) | (true,Ast0.Context) | (true,Ast0.PureContext) ->
+ (match lst with
+ [x] ->
+ if (Ast0.lub_pure (is_pure x) pure) = pure
+ then add_binding name (builder1 lst)
+ else return_false (NotPure (pure,term name,builder1 lst))
+ | _ -> return_false (NotPureLength (term name)))
+ | (false,_) | (_,Ast0.Impure) -> add_binding name (builder2 lst) in
+
+ let add_pure_binding name pure is_pure builder x =
+ match (checks_needed,pure) with
+ (true,Ast0.Pure) | (true,Ast0.Context) | (true,Ast0.PureContext) ->
+ if (Ast0.lub_pure (is_pure x) pure) = pure
+ then add_binding name (builder x)
+ else return_false (NotPure (pure,term name, builder x))
+ | (false,_) | (_,Ast0.Impure) -> add_binding name (builder x) in
+
+ let do_elist_match builder el lst =
+ match Ast0.unwrap el with
+ Ast0.MetaExprList(name,lenname,pure) ->
+ (*how to handle lenname? should it be an option type and always None?*)
+ failwith "expr list pattern not supported in iso"
+ (*add_pure_list_binding name pure
+ pure_sp_code.V0.combiner_expression
+ (function lst -> Ast0.ExprTag(List.hd lst))
+ (function lst -> Ast0.DotsExprTag(build_dots builder lst))
+ lst*)
+ | _ -> failwith "not possible" in
+
+ let do_plist_match builder pl lst =
+ match Ast0.unwrap pl with
+ Ast0.MetaParamList(name,lename,pure) ->
+ failwith "param list pattern not supported in iso"
+ (*add_pure_list_binding name pure
+ pure_sp_code.V0.combiner_parameter
+ (function lst -> Ast0.ParamTag(List.hd lst))
+ (function lst -> Ast0.DotsParamTag(build_dots builder lst))
+ lst*)
+ | _ -> failwith "not possible" in
+
+ let do_slist_match builder sl lst =
+ match Ast0.unwrap sl with
+ Ast0.MetaStmtList(name,pure) ->
+ add_pure_list_binding name pure
+ pure_sp_code.V0.combiner_statement
+ (function lst -> Ast0.StmtTag(List.hd lst))
+ (function lst -> Ast0.DotsStmtTag(build_dots builder lst))
+ lst
+ | _ -> failwith "not possible" in
+
+ let do_nolist_match _ _ = failwith "not possible" in
+
+ let rec match_ident pattern id =
+ match Ast0.unwrap pattern with
+ Ast0.MetaId(name,_,pure) ->
+ (add_pure_binding name pure pure_sp_code.V0.combiner_ident
+ (function id -> Ast0.IdentTag id) id)
+ | Ast0.MetaFunc(name,_,pure) -> failwith "metafunc not supported"
+ | Ast0.MetaLocalFunc(name,_,pure) -> failwith "metalocalfunc not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context id
+ then
+ match (up,Ast0.unwrap id) with
+ (Ast0.Id(namea),Ast0.Id(nameb)) ->
+ if mcode_equal namea nameb
+ then check_mcode namea nameb
+ else return false
+ | (Ast0.OptIdent(ida),Ast0.OptIdent(idb))
+ | (Ast0.UniqueIdent(ida),Ast0.UniqueIdent(idb)) ->
+ match_ident ida idb
+ | (_,Ast0.OptIdent(idb))
+ | (_,Ast0.UniqueIdent(idb)) -> match_ident pattern idb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.IdentTag id)) in
+
+ (* should we do something about matching metavars against ...? *)
+ let rec match_expr pattern expr =
+ match Ast0.unwrap pattern with
+ Ast0.MetaExpr(name,_,ty,form,pure) ->
+ let form_ok =
+ match (form,expr) with
+ (Ast.ANY,_) -> true
+ | (Ast.CONST,e) ->
+ let rec matches e =
+ match Ast0.unwrap e with
+ Ast0.Constant(c) -> true
+ | Ast0.Cast(lp,ty,rp,e) -> matches e
+ | Ast0.SizeOfExpr(se,exp) -> true
+ | Ast0.SizeOfType(se,lp,ty,rp) -> true
+ | Ast0.MetaExpr(nm,_,_,Ast.CONST,p) ->
+ (Ast0.lub_pure p pure) = pure
+ | _ -> false in
+ matches e
+ | (Ast.ID,e) | (Ast.LocalID,e) ->
+ let rec matches e =
+ match Ast0.unwrap e with
+ Ast0.Ident(c) -> true
+ | Ast0.Cast(lp,ty,rp,e) -> matches e
+ | Ast0.MetaExpr(nm,_,_,Ast.ID,p) ->
+ (Ast0.lub_pure p pure) = pure
+ | _ -> false in
+ matches e in
+ if form_ok
+ then
+ match ty with
+ Some ts ->
+ if List.exists
+ (function Type_cocci.MetaType(_,_,_) -> true | _ -> false)
+ ts
+ then
+ (match ts with
+ [Type_cocci.MetaType(tyname,_,_)] ->
+ let expty =
+ match (Ast0.unwrap expr,Ast0.get_type expr) with
+ (* easier than updating type inferencer to manage multiple
+ types *)
+ (Ast0.MetaExpr(_,_,Some tts,_,_),_) -> Some tts
+ | (_,Some ty) -> Some [ty]
+ | _ -> None in
+ (match expty with
+ Some expty ->
+ let tyname = Ast0.rewrap_mcode name tyname in
+ (function bindings ->
+ let attempts =
+ List.map
+ (function expty ->
+ (try
+ conjunct_bindings
+ (add_pure_binding tyname Ast0.Impure
+ (function _ -> Ast0.Impure)
+ (function ty -> Ast0.TypeCTag ty)
+ (Ast0.rewrap expr
+ (Ast0.reverse_type expty)))
+ (add_pure_binding name pure
+ pure_sp_code.V0.combiner_expression
+ (function expr -> Ast0.ExprTag expr)
+ expr)
+ bindings
+ with Ast0.TyConv ->
+ Printf.printf "warning: unconvertible type";
+ return false bindings))
+ expty in
+ match
+ List.concat
+ (List.map (function Fail _ -> [] | OK x -> x)
+ attempts)
+ with
+ [] -> Fail NonMatch
+ | x -> OK x)
+ | _ ->
+ (*Printf.printf
+ "warning: type metavar can only match one type";*)
+ return false)
+ | _ ->
+ failwith
+ "mixture of metatype and other types not supported")
+ else
+ let expty = Ast0.get_type expr in
+ if List.exists (function t -> Type_cocci.compatible t expty) ts
+ then
+ add_pure_binding name pure
+ pure_sp_code.V0.combiner_expression
+ (function expr -> Ast0.ExprTag expr)
+ expr
+ else return false
+ | None ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_expression
+ (function expr -> Ast0.ExprTag expr)
+ expr
+ else return false
+ | Ast0.MetaErr(namea,_,pure) -> failwith "metaerr not supported"
+ | Ast0.MetaExprList(_,_,_) -> failwith "metaexprlist not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context expr
+ then
+ match (up,Ast0.unwrap expr) with
+ (Ast0.Ident(ida),Ast0.Ident(idb)) ->
+ match_ident ida idb
+ | (Ast0.Constant(consta),Ast0.Constant(constb)) ->
+ if mcode_equal consta constb
+ then check_mcode consta constb
+ else return false
+ | (Ast0.FunCall(fna,lp1,argsa,rp1),Ast0.FunCall(fnb,lp,argsb,rp)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp; match_expr fna fnb;
+ match_dots match_expr is_elist_matcher do_elist_match
+ argsa argsb]
+ | (Ast0.Assignment(lefta,opa,righta,_),
+ Ast0.Assignment(leftb,opb,rightb,_)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_many_bindings
+ [check_mcode opa opb; match_expr lefta leftb;
+ match_expr righta rightb]
+ else return false
+ | (Ast0.CondExpr(exp1a,lp1,exp2a,rp1,exp3a),
+ Ast0.CondExpr(exp1b,lp,exp2b,rp,exp3b)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ match_expr exp1a exp1b; match_option match_expr exp2a exp2b;
+ match_expr exp3a exp3b]
+ | (Ast0.Postfix(expa,opa),Ast0.Postfix(expb,opb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_bindings (check_mcode opa opb) (match_expr expa expb)
+ else return false
+ | (Ast0.Infix(expa,opa),Ast0.Infix(expb,opb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_bindings (check_mcode opa opb) (match_expr expa expb)
+ else return false
+ | (Ast0.Unary(expa,opa),Ast0.Unary(expb,opb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_bindings (check_mcode opa opb) (match_expr expa expb)
+ else return false
+ | (Ast0.Binary(lefta,opa,righta),Ast0.Binary(leftb,opb,rightb)) ->
+ if mcode_equal opa opb
+ then
+ conjunct_many_bindings
+ [check_mcode opa opb; match_expr lefta leftb;
+ match_expr righta rightb]
+ else return false
+ | (Ast0.Paren(lp1,expa,rp1),Ast0.Paren(lp,expb,rp)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp; match_expr expa expb]
+ | (Ast0.ArrayAccess(exp1a,lb1,exp2a,rb1),
+ Ast0.ArrayAccess(exp1b,lb,exp2b,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_expr exp1a exp1b; match_expr exp2a exp2b]
+ | (Ast0.RecordAccess(expa,opa,fielda),
+ Ast0.RecordAccess(expb,op,fieldb))
+ | (Ast0.RecordPtAccess(expa,opa,fielda),
+ Ast0.RecordPtAccess(expb,op,fieldb)) ->
+ conjunct_many_bindings
+ [check_mcode opa op; match_expr expa expb;
+ match_ident fielda fieldb]
+ | (Ast0.Cast(lp1,tya,rp1,expa),Ast0.Cast(lp,tyb,rp,expb)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ match_typeC tya tyb; match_expr expa expb]
+ | (Ast0.SizeOfExpr(szf1,expa),Ast0.SizeOfExpr(szf,expb)) ->
+ conjunct_bindings (check_mcode szf1 szf) (match_expr expa expb)
+ | (Ast0.SizeOfType(szf1,lp1,tya,rp1),
+ Ast0.SizeOfType(szf,lp,tyb,rp)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode szf1 szf; match_typeC tya tyb]
+ | (Ast0.TypeExp(tya),Ast0.TypeExp(tyb)) ->
+ match_typeC tya tyb
+ | (Ast0.EComma(cm1),Ast0.EComma(cm)) -> check_mcode cm1 cm
+ | (Ast0.DisjExpr(_,expsa,_,_),_) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.NestExpr(_,exp_dotsa,_,_,_),_) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.Edots(d,None),Ast0.Edots(d1,None))
+ | (Ast0.Ecircles(d,None),Ast0.Ecircles(d1,None))
+ | (Ast0.Estars(d,None),Ast0.Estars(d1,None)) -> check_mcode d d1
+ | (Ast0.Edots(ed,None),Ast0.Edots(ed1,Some wc))
+ | (Ast0.Ecircles(ed,None),Ast0.Ecircles(ed1,Some wc))
+ | (Ast0.Estars(ed,None),Ast0.Estars(ed1,Some wc)) ->
+ (* hope that mcode of edots is unique somehow *)
+ conjunct_bindings (check_mcode ed ed1)
+ (let (edots_whencode_allowed,_,_) = whencode_allowed in
+ if edots_whencode_allowed
+ then add_dot_binding ed (Ast0.ExprTag wc)
+ else
+ (Printf.printf
+ "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Edots(_,Some _),_) | (Ast0.Ecircles(_,Some _),_)
+ | (Ast0.Estars(_,Some _),_) ->
+ failwith "whencode not allowed in a pattern1"
+ | (Ast0.OptExp(expa),Ast0.OptExp(expb))
+ | (Ast0.UniqueExp(expa),Ast0.UniqueExp(expb)) -> match_expr expa expb
+ | (_,Ast0.OptExp(expb))
+ | (_,Ast0.UniqueExp(expb)) -> match_expr pattern expb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.ExprTag expr))
+
+(* the special case for function types prevents the eg T X; -> T X = E; iso
+ from applying, which doesn't seem very relevant, but it also avoids a
+ mysterious bug that is obtained with eg int attach(...); *)
+ and match_typeC pattern t =
+ match Ast0.unwrap pattern with
+ Ast0.MetaType(name,pure) ->
+ (match Ast0.unwrap t with
+ Ast0.FunctionType(tya,lp1a,paramsa,rp1a) -> return false
+ | _ ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_typeC
+ (function ty -> Ast0.TypeCTag ty)
+ t)
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context t
+ then
+ match (up,Ast0.unwrap t) with
+ (Ast0.ConstVol(cva,tya),Ast0.ConstVol(cvb,tyb)) ->
+ if mcode_equal cva cvb
+ then
+ conjunct_bindings (check_mcode cva cvb) (match_typeC tya tyb)
+ else return false
+ | (Ast0.BaseType(tya,signa),Ast0.BaseType(tyb,signb)) ->
+ if (mcode_equal tya tyb &&
+ bool_match_option mcode_equal signa signb)
+ then
+ conjunct_bindings (check_mcode tya tyb)
+ (match_option check_mcode signa signb)
+ else return false
+ | (Ast0.ImplicitInt(signa),Ast0.ImplicitInt(signb)) ->
+ if mcode_equal signa signb
+ then check_mcode signa signb
+ else return false
+ | (Ast0.Pointer(tya,star1),Ast0.Pointer(tyb,star)) ->
+ conjunct_bindings (check_mcode star1 star) (match_typeC tya tyb)
+ | (Ast0.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a),
+ Ast0.FunctionPointer(tyb,lp1b,starb,rp1b,lp2b,paramsb,rp2b)) ->
+ conjunct_many_bindings
+ [check_mcode stara starb; check_mcode lp1a lp1b;
+ check_mcode rp1a rp1b; check_mcode lp2a lp2b;
+ check_mcode rp2a rp2b; match_typeC tya tyb;
+ match_dots match_param is_plist_matcher
+ do_plist_match paramsa paramsb]
+ | (Ast0.FunctionType(tya,lp1a,paramsa,rp1a),
+ Ast0.FunctionType(tyb,lp1b,paramsb,rp1b)) ->
+ conjunct_many_bindings
+ [check_mcode lp1a lp1b; check_mcode rp1a rp1b;
+ match_option match_typeC tya tyb;
+ match_dots match_param is_plist_matcher do_plist_match
+ paramsa paramsb]
+ | (Ast0.Array(tya,lb1,sizea,rb1),Ast0.Array(tyb,lb,sizeb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_typeC tya tyb; match_option match_expr sizea sizeb]
+ | (Ast0.StructUnionName(kinda,Some namea),
+ Ast0.StructUnionName(kindb,Some nameb)) ->
+ if mcode_equal kinda kindb
+ then
+ conjunct_bindings (check_mcode kinda kindb)
+ (match_ident namea nameb)
+ else return false
+ | (Ast0.StructUnionDef(tya,lb1,declsa,rb1),
+ Ast0.StructUnionDef(tyb,lb,declsb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_typeC tya tyb;
+ match_dots match_decl no_list do_nolist_match declsa declsb]
+ | (Ast0.TypeName(namea),Ast0.TypeName(nameb)) ->
+ if mcode_equal namea nameb
+ then check_mcode namea nameb
+ else return false
+ | (Ast0.DisjType(_,typesa,_,_),Ast0.DisjType(_,typesb,_,_)) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.OptType(tya),Ast0.OptType(tyb))
+ | (Ast0.UniqueType(tya),Ast0.UniqueType(tyb)) -> match_typeC tya tyb
+ | (_,Ast0.OptType(tyb))
+ | (_,Ast0.UniqueType(tyb)) -> match_typeC pattern tyb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.TypeCTag t))
+
+ and match_decl pattern d =
+ if not(checks_needed) or not(context_required) or is_context d
+ then
+ match (Ast0.unwrap pattern,Ast0.unwrap d) with
+ (Ast0.Init(stga,tya,ida,eq1,inia,sc1),
+ Ast0.Init(stgb,tyb,idb,eq,inib,sc)) ->
+ if bool_match_option mcode_equal stga stgb
+ then
+ conjunct_many_bindings
+ [check_mcode eq1 eq; check_mcode sc1 sc;
+ match_option check_mcode stga stgb;
+ match_typeC tya tyb; match_ident ida idb;
+ match_init inia inib]
+ else return false
+ | (Ast0.UnInit(stga,tya,ida,sc1),Ast0.UnInit(stgb,tyb,idb,sc)) ->
+ if bool_match_option mcode_equal stga stgb
+ then
+ conjunct_many_bindings
+ [check_mcode sc1 sc; match_option check_mcode stga stgb;
+ match_typeC tya tyb; match_ident ida idb]
+ else return false
+ | (Ast0.MacroDecl(namea,lp1,argsa,rp1,sc1),
+ Ast0.MacroDecl(nameb,lp,argsb,rp,sc)) ->
+ conjunct_many_bindings
+ [match_ident namea nameb;
+ check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode sc1 sc;
+ match_dots match_expr is_elist_matcher do_elist_match
+ argsa argsb]
+ | (Ast0.TyDecl(tya,sc1),Ast0.TyDecl(tyb,sc)) ->
+ conjunct_bindings (check_mcode sc1 sc) (match_typeC tya tyb)
+ | (Ast0.Typedef(stga,tya,ida,sc1),Ast0.Typedef(stgb,tyb,idb,sc)) ->
+ conjunct_bindings (check_mcode sc1 sc)
+ (conjunct_bindings (match_typeC tya tyb) (match_typeC ida idb))
+ | (Ast0.DisjDecl(_,declsa,_,_),Ast0.DisjDecl(_,declsb,_,_)) ->
+ failwith "not allowed in the pattern of an isomorphism"
+ | (Ast0.Ddots(d1,None),Ast0.Ddots(d,None)) -> check_mcode d1 d
+ | (Ast0.Ddots(dd,None),Ast0.Ddots(d,Some wc)) ->
+ conjunct_bindings (check_mcode dd d)
+ (* hope that mcode of ddots is unique somehow *)
+ (let (ddots_whencode_allowed,_,_) = whencode_allowed in
+ if ddots_whencode_allowed
+ then add_dot_binding dd (Ast0.DeclTag wc)
+ else
+ (Printf.printf "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Ddots(_,Some _),_) ->
+ failwith "whencode not allowed in a pattern1"
+
+ | (Ast0.OptDecl(decla),Ast0.OptDecl(declb))
+ | (Ast0.UniqueDecl(decla),Ast0.UniqueDecl(declb)) ->
+ match_decl decla declb
+ | (_,Ast0.OptDecl(declb))
+ | (_,Ast0.UniqueDecl(declb)) ->
+ match_decl pattern declb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.DeclTag d))
+
+ and match_init pattern i =
+ if not(checks_needed) or not(context_required) or is_context i
+ then
+ match (Ast0.unwrap pattern,Ast0.unwrap i) with
+ (Ast0.InitExpr(expa),Ast0.InitExpr(expb)) ->
+ match_expr expa expb
+ | (Ast0.InitList(lb1,initlista,rb1),Ast0.InitList(lb,initlistb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb; check_mcode rb1 rb;
+ match_dots match_init no_list do_nolist_match
+ initlista initlistb]
+ | (Ast0.InitGccDotName(d1,namea,e1,inia),
+ Ast0.InitGccDotName(d,nameb,e,inib)) ->
+ conjunct_many_bindings
+ [check_mcode d1 d; check_mcode e1 e;
+ match_ident namea nameb; match_init inia inib]
+ | (Ast0.InitGccName(namea,c1,inia),Ast0.InitGccName(nameb,c,inib)) ->
+ conjunct_many_bindings
+ [check_mcode c1 c; match_ident namea nameb;
+ match_init inia inib]
+ | (Ast0.InitGccIndex(lb1,expa,rb1,e1,inia),
+ Ast0.InitGccIndex(lb2,expb,rb2,e2,inib)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb2; check_mcode rb1 rb2; check_mcode e1 e2;
+ match_expr expa expb; match_init inia inib]
+ | (Ast0.InitGccRange(lb1,exp1a,d1,exp2a,rb1,e1,inia),
+ Ast0.InitGccRange(lb2,exp1b,d2,exp2b,rb2,e2,inib)) ->
+ conjunct_many_bindings
+ [check_mcode lb1 lb2; check_mcode d1 d2;
+ check_mcode rb1 rb2; check_mcode e1 e2;
+ match_expr exp1a exp1b; match_expr exp2a exp2b;
+ match_init inia inib]
+ | (Ast0.IComma(c1),Ast0.IComma(c)) -> check_mcode c1 c
+ | (Ast0.Idots(d1,None),Ast0.Idots(d,None)) -> check_mcode d1 d
+ | (Ast0.Idots(id,None),Ast0.Idots(d,Some wc)) ->
+ conjunct_bindings (check_mcode id d)
+ (* hope that mcode of edots is unique somehow *)
+ (let (_,idots_whencode_allowed,_) = whencode_allowed in
+ if idots_whencode_allowed
+ then add_dot_binding id (Ast0.InitTag wc)
+ else
+ (Printf.printf "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Idots(_,Some _),_) ->
+ failwith "whencode not allowed in a pattern2"
+ | (Ast0.OptIni(ia),Ast0.OptIni(ib))
+ | (Ast0.UniqueIni(ia),Ast0.UniqueIni(ib)) -> match_init ia ib
+ | (_,Ast0.OptIni(ib))
+ | (_,Ast0.UniqueIni(ib)) -> match_init pattern ib
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.InitTag i))
+
+ and match_param pattern p =
+ match Ast0.unwrap pattern with
+ Ast0.MetaParam(name,pure) ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_parameter
+ (function p -> Ast0.ParamTag p)
+ p
+ | Ast0.MetaParamList(name,_,pure) -> failwith "metaparamlist not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context p
+ then
+ match (up,Ast0.unwrap p) with
+ (Ast0.VoidParam(tya),Ast0.VoidParam(tyb)) -> match_typeC tya tyb
+ | (Ast0.Param(tya,ida),Ast0.Param(tyb,idb)) ->
+ conjunct_bindings (match_typeC tya tyb)
+ (match_option match_ident ida idb)
+ | (Ast0.PComma(c1),Ast0.PComma(c)) -> check_mcode c1 c
+ | (Ast0.Pdots(d1),Ast0.Pdots(d))
+ | (Ast0.Pcircles(d1),Ast0.Pcircles(d)) -> check_mcode d1 d
+ | (Ast0.OptParam(parama),Ast0.OptParam(paramb))
+ | (Ast0.UniqueParam(parama),Ast0.UniqueParam(paramb)) ->
+ match_param parama paramb
+ | (_,Ast0.OptParam(paramb))
+ | (_,Ast0.UniqueParam(paramb)) -> match_param pattern paramb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.ParamTag p))
+
+ and match_statement pattern s =
+ match Ast0.unwrap pattern with
+ Ast0.MetaStmt(name,pure) ->
+ (match Ast0.unwrap s with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_) ->
+ return false (* ... is not a single statement *)
+ | _ ->
+ add_pure_binding name pure pure_sp_code.V0.combiner_statement
+ (function ty -> Ast0.StmtTag ty)
+ s)
+ | Ast0.MetaStmtList(name,pure) -> failwith "metastmtlist not supported"
+ | up ->
+ if not(checks_needed) or not(context_required) or is_context s
+ then
+ match (up,Ast0.unwrap s) with
+ (Ast0.FunDecl(_,fninfoa,namea,lp1,paramsa,rp1,lb1,bodya,rb1),
+ Ast0.FunDecl(_,fninfob,nameb,lp,paramsb,rp,lb,bodyb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode lb1 lb; check_mcode rb1 rb;
+ match_fninfo fninfoa fninfob; match_ident namea nameb;
+ match_dots match_param is_plist_matcher do_plist_match
+ paramsa paramsb;
+ match_dots match_statement is_slist_matcher do_slist_match
+ bodya bodyb]
+ | (Ast0.Decl(_,decla),Ast0.Decl(_,declb)) ->
+ match_decl decla declb
+ | (Ast0.Seq(lb1,bodya,rb1),Ast0.Seq(lb,bodyb,rb)) ->
+ (* seqs can only match if they are all minus (plus code
+ allowed) or all context (plus code not allowed in the body).
+ we could be more permissive if the expansions of the isos are
+ also all seqs, but this would be hard to check except at top
+ level, and perhaps not worth checking even in that case.
+ Overall, the issue is that braces are used where single
+ statements are required, and something not satisfying these
+ conditions can cause a single statement to become a
+ non-single statement after the transformation.
+
+ example: if { ... -foo(); ... }
+ if we let the sequence convert to just -foo();
+ then we produce invalid code. For some reason,
+ single_statement can't deal with this case, perhaps because
+ it starts introducing too many braces? don't remember the
+ exact problem...
+ *)
+ conjunct_bindings (check_mcode lb1 lb)
+ (conjunct_bindings (check_mcode rb1 rb)
+ (if not(checks_needed) or is_minus s or
+ (is_context s &&
+ List.for_all is_pure_context (Ast0.undots bodyb))
+ then
+ match_dots match_statement is_slist_matcher do_slist_match
+ bodya bodyb
+ else return_false (Braces(s))))
+ | (Ast0.ExprStatement(expa,sc1),Ast0.ExprStatement(expb,sc)) ->
+ conjunct_bindings (check_mcode sc1 sc) (match_expr expa expb)
+ | (Ast0.IfThen(if1,lp1,expa,rp1,branch1a,_),
+ Ast0.IfThen(if2,lp2,expb,rp2,branch1b,_)) ->
+ conjunct_many_bindings
+ [check_mcode if1 if2; check_mcode lp1 lp2;
+ check_mcode rp1 rp2;
+ match_expr expa expb;
+ match_statement branch1a branch1b]
+ | (Ast0.IfThenElse(if1,lp1,expa,rp1,branch1a,e1,branch2a,_),
+ Ast0.IfThenElse(if2,lp2,expb,rp2,branch1b,e2,branch2b,_)) ->
+ conjunct_many_bindings
+ [check_mcode if1 if2; check_mcode lp1 lp2;
+ check_mcode rp1 rp2; check_mcode e1 e2;
+ match_expr expa expb;
+ match_statement branch1a branch1b;
+ match_statement branch2a branch2b]
+ | (Ast0.While(w1,lp1,expa,rp1,bodya,_),
+ Ast0.While(w,lp,expb,rp,bodyb,_)) ->
+ conjunct_many_bindings
+ [check_mcode w1 w; check_mcode lp1 lp;
+ check_mcode rp1 rp; match_expr expa expb;
+ match_statement bodya bodyb]
+ | (Ast0.Do(d1,bodya,w1,lp1,expa,rp1,_),
+ Ast0.Do(d,bodyb,w,lp,expb,rp,_)) ->
+ conjunct_many_bindings
+ [check_mcode d1 d; check_mcode w1 w; check_mcode lp1 lp;
+ check_mcode rp1 rp; match_statement bodya bodyb;
+ match_expr expa expb]
+ | (Ast0.For(f1,lp1,e1a,sc1a,e2a,sc2a,e3a,rp1,bodya,_),
+ Ast0.For(f,lp,e1b,sc1b,e2b,sc2b,e3b,rp,bodyb,_)) ->
+ conjunct_many_bindings
+ [check_mcode f1 f; check_mcode lp1 lp; check_mcode sc1a sc1b;
+ check_mcode sc2a sc2b; check_mcode rp1 rp;
+ match_option match_expr e1a e1b;
+ match_option match_expr e2a e2b;
+ match_option match_expr e3a e3b;
+ match_statement bodya bodyb]
+ | (Ast0.Iterator(nma,lp1,argsa,rp1,bodya,_),
+ Ast0.Iterator(nmb,lp,argsb,rp,bodyb,_)) ->
+ conjunct_many_bindings
+ [match_ident nma nmb;
+ check_mcode lp1 lp; check_mcode rp1 rp;
+ match_dots match_expr is_elist_matcher do_elist_match
+ argsa argsb;
+ match_statement bodya bodyb]
+ | (Ast0.Switch(s1,lp1,expa,rp1,lb1,casesa,rb1),
+ Ast0.Switch(s,lp,expb,rp,lb,casesb,rb)) ->
+ conjunct_many_bindings
+ [check_mcode s1 s; check_mcode lp1 lp; check_mcode rp1 rp;
+ check_mcode lb1 lb; check_mcode rb1 rb;
+ match_expr expa expb;
+ match_dots match_case_line no_list do_nolist_match
+ casesa casesb]
+ | (Ast0.Break(b1,sc1),Ast0.Break(b,sc))
+ | (Ast0.Continue(b1,sc1),Ast0.Continue(b,sc)) ->
+ conjunct_bindings (check_mcode b1 b) (check_mcode sc1 sc)
+ | (Ast0.Label(l1,c1),Ast0.Label(l2,c)) ->
+ conjunct_bindings (match_ident l1 l2) (check_mcode c1 c)
+ | (Ast0.Goto(g1,l1,sc1),Ast0.Goto(g,l2,sc)) ->
+ conjunct_many_bindings
+ [check_mcode g1 g; check_mcode sc1 sc; match_ident l1 l2]
+ | (Ast0.Return(r1,sc1),Ast0.Return(r,sc)) ->
+ conjunct_bindings (check_mcode r1 r) (check_mcode sc1 sc)
+ | (Ast0.ReturnExpr(r1,expa,sc1),Ast0.ReturnExpr(r,expb,sc)) ->
+ conjunct_many_bindings
+ [check_mcode r1 r; check_mcode sc1 sc; match_expr expa expb]
+ | (Ast0.Disj(_,statement_dots_lista,_,_),_) ->
+ failwith "disj not supported in patterns"
+ | (Ast0.Nest(_,stmt_dotsa,_,_,_),_) ->
+ failwith "nest not supported in patterns"
+ | (Ast0.Exp(expa),Ast0.Exp(expb)) -> match_expr expa expb
+ | (Ast0.TopExp(expa),Ast0.TopExp(expb)) -> match_expr expa expb
+ | (Ast0.Exp(expa),Ast0.TopExp(expb)) -> match_expr expa expb
+ | (Ast0.Ty(tya),Ast0.Ty(tyb)) -> match_typeC tya tyb
+ | (Ast0.Dots(d,[]),Ast0.Dots(d1,wc))
+ | (Ast0.Circles(d,[]),Ast0.Circles(d1,wc))
+ | (Ast0.Stars(d,[]),Ast0.Stars(d1,wc)) ->
+ (match wc with
+ [] -> check_mcode d d1
+ | _ ->
+ let (_,_,dots_whencode_allowed) = whencode_allowed in
+ if dots_whencode_allowed
+ then
+ conjunct_bindings (check_mcode d d1)
+ (List.fold_left
+ (function prev ->
+ function
+ | Ast0.WhenNot wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.DotsStmtTag wc))
+ | Ast0.WhenAlways wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d (Ast0.StmtTag wc))
+ | Ast0.WhenNotTrue wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.IsoWhenTTag wc))
+ | Ast0.WhenNotFalse wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.IsoWhenFTag wc))
+ | Ast0.WhenModifier(x) ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.IsoWhenTag x)))
+ (return true) wc)
+ else
+ (Printf.printf
+ "warning: not applying iso because of whencode";
+ return false))
+ | (Ast0.Dots(_,_::_),_) | (Ast0.Circles(_,_::_),_)
+ | (Ast0.Stars(_,_::_),_) ->
+ failwith "whencode not allowed in a pattern3"
+ | (Ast0.OptStm(rea),Ast0.OptStm(reb))
+ | (Ast0.UniqueStm(rea),Ast0.UniqueStm(reb)) ->
+ match_statement rea reb
+ | (_,Ast0.OptStm(reb))
+ | (_,Ast0.UniqueStm(reb)) -> match_statement pattern reb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.StmtTag s))
+
+ (* first should provide a subset of the information in the second *)
+ and match_fninfo patterninfo cinfo =
+ let patterninfo = List.sort compare patterninfo in
+ let cinfo = List.sort compare cinfo in
+ let rec loop = function
+ (Ast0.FStorage(sta)::resta,Ast0.FStorage(stb)::restb) ->
+ if mcode_equal sta stb
+ then conjunct_bindings (check_mcode sta stb) (loop (resta,restb))
+ else return false
+ | (Ast0.FType(tya)::resta,Ast0.FType(tyb)::restb) ->
+ conjunct_bindings (match_typeC tya tyb) (loop (resta,restb))
+ | (Ast0.FInline(ia)::resta,Ast0.FInline(ib)::restb) ->
+ if mcode_equal ia ib
+ then conjunct_bindings (check_mcode ia ib) (loop (resta,restb))
+ else return false
+ | (Ast0.FAttr(ia)::resta,Ast0.FAttr(ib)::restb) ->
+ if mcode_equal ia ib
+ then conjunct_bindings (check_mcode ia ib) (loop (resta,restb))
+ else return false
+ | (x::resta,((y::_) as restb)) ->
+ (match compare x y with
+ -1 -> return false
+ | 1 -> loop (resta,restb)
+ | _ -> failwith "not possible")
+ | _ -> return false in
+ loop (patterninfo,cinfo)
+
+ and match_case_line pattern c =
+ if not(checks_needed) or not(context_required) or is_context c
+ then
+ match (Ast0.unwrap pattern,Ast0.unwrap c) with
+ (Ast0.Default(d1,c1,codea),Ast0.Default(d,c,codeb)) ->
+ conjunct_many_bindings
+ [check_mcode d1 d; check_mcode c1 c;
+ match_dots match_statement is_slist_matcher do_slist_match
+ codea codeb]
+ | (Ast0.Case(ca1,expa,c1,codea),Ast0.Case(ca,expb,c,codeb)) ->
+ conjunct_many_bindings
+ [check_mcode ca1 ca; check_mcode c1 c; match_expr expa expb;
+ match_dots match_statement is_slist_matcher do_slist_match
+ codea codeb]
+ | (Ast0.OptCase(ca),Ast0.OptCase(cb)) -> match_case_line ca cb
+ | (_,Ast0.OptCase(cb)) -> match_case_line pattern cb
+ | _ -> return false
+ else return_false (ContextRequired (Ast0.CaseLineTag c)) in
+
+ let match_statement_dots x y =
+ match_dots match_statement is_slist_matcher do_slist_match x y in
+
+ (match_expr, match_decl, match_statement, match_typeC,
+ match_statement_dots)
+
+let match_expr dochecks context_required whencode_allowed =
+ let (fn,_,_,_,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_decl dochecks context_required whencode_allowed =
+ let (_,fn,_,_,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_statement dochecks context_required whencode_allowed =
+ let (_,_,fn,_,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_typeC dochecks context_required whencode_allowed =
+ let (_,_,_,fn,_) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+let match_statement_dots dochecks context_required whencode_allowed =
+ let (_,_,_,_,fn) = match_maker dochecks context_required whencode_allowed in
+ fn
+
+(* --------------------------------------------------------------------- *)
+(* make an entire tree MINUS *)
+
+let make_minus =
+ let mcode (term,arity,info,mcodekind,pos) =
+ let new_mcodekind =
+ match mcodekind with
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) -> Ast0.MINUS(ref([],Ast0.default_token_info))
+ | _ -> failwith "make_minus: unexpected befaft")
+ | Ast0.MINUS(mc) -> mcodekind (* in the part copied from the src term *)
+ | _ -> failwith "make_minus mcode: unexpected mcodekind" in
+ (term,arity,info,new_mcodekind,pos) in
+
+ let update_mc mcodekind e =
+ match !mcodekind with
+ Ast0.CONTEXT(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) ->
+ mcodekind := Ast0.MINUS(ref([],Ast0.default_token_info))
+ | _ -> failwith "make_minus: unexpected befaft")
+ | Ast0.MINUS(_mc) -> () (* in the part copied from the src term *)
+ | Ast0.PLUS -> failwith "make_minus donothing: unexpected plus mcodekind"
+ | _ -> failwith "make_minus donothing: unexpected mcodekind" in
+
+ let donothing r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ let e = k e in update_mc mcodekind e; e in
+
+ (* special case for whencode, because it isn't processed by contextneg,
+ since it doesn't appear in the + code *)
+ (* cases for dots and nests *)
+ let expression r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Edots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Edots(mcode d,whencode))
+ | Ast0.Ecircles(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Ecircles(mcode d,whencode))
+ | Ast0.Estars(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Estars(mcode d,whencode))
+ | Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ update_mc mcodekind e;
+ Ast0.rewrap e
+ (Ast0.NestExpr(mcode starter,
+ r.V0.rebuilder_expression_dots expr_dots,
+ mcode ender,whencode,multi))
+ | _ -> donothing r k e in
+
+ let declaration r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Ddots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Ddots(mcode d,whencode))
+ | _ -> donothing r k e in
+
+ let statement r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Dots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Dots(mcode d,whencode))
+ | Ast0.Circles(d,whencode) ->
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Circles(mcode d,whencode))
+ | Ast0.Stars(d,whencode) ->
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Stars(mcode d,whencode))
+ | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
+ update_mc mcodekind e;
+ Ast0.rewrap e
+ (Ast0.Nest(mcode starter,r.V0.rebuilder_statement_dots stmt_dots,
+ mcode ender,whencode,multi))
+ | _ -> donothing r k e in
+
+ let initialiser r k e =
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.Idots(d,whencode) ->
+ (*don't recurse because whencode hasn't been processed by context_neg*)
+ update_mc mcodekind e; Ast0.rewrap e (Ast0.Idots(mcode d,whencode))
+ | _ -> donothing r k e in
+
+ let dots r k e =
+ let info = Ast0.get_info e in
+ let mcodekind = Ast0.get_mcodekind_ref e in
+ match Ast0.unwrap e with
+ Ast0.DOTS([]) ->
+ (* if context is - this should be - as well. There are no tokens
+ here though, so the bottom-up minusifier in context_neg leaves it
+ as mixed. It would be better to fix context_neg, but that would
+ require a special case for each term with a dots subterm. *)
+ (match !mcodekind with
+ Ast0.MIXED(mc) ->
+ (match !mc with
+ (Ast.NOTHING,_,_) ->
+ mcodekind := Ast0.MINUS(ref([],Ast0.default_token_info));
+ e
+ | _ -> failwith "make_minus: unexpected befaft")
+ (* code already processed by an enclosing iso *)
+ | Ast0.MINUS(mc) -> e
+ | _ ->
+ failwith
+ (Printf.sprintf
+ "%d: make_minus donothingxxx: unexpected mcodekind"
+ info.Ast0.line_start))
+ | _ -> donothing r k e in
+
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ dots dots dots dots dots dots
+ donothing expression donothing initialiser donothing declaration
+ statement donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* rebuild mcode cells in an instantiated alt *)
+
+(* mcodes will be side effected later with plus code, so we have to copy
+ them on instantiating an isomorphism. One could wonder whether it would
+ be better not to use side-effects, but they are convenient for insert_plus
+ where is it useful to manipulate a list of the mcodes but side-effect a
+ tree *)
+(* hmm... Insert_plus is called before Iso_pattern... *)
+let rebuild_mcode start_line =
+ let copy_mcodekind = function
+ Ast0.CONTEXT(mc) -> Ast0.CONTEXT(ref (!mc))
+ | Ast0.MINUS(mc) -> Ast0.MINUS(ref (!mc))
+ | Ast0.MIXED(mc) -> Ast0.MIXED(ref (!mc))
+ | Ast0.PLUS ->
+ (* this function is used elsewhere where we need to rebuild the
+ indices, and so we allow PLUS code as well *)
+ Ast0.PLUS in
+
+ let mcode (term,arity,info,mcodekind,pos) =
+ let info =
+ match start_line with
+ Some x -> {info with Ast0.line_start = x; Ast0.line_end = x}
+ | None -> info in
+ (term,arity,info,copy_mcodekind mcodekind,pos) in
+
+ let copy_one x =
+ let old_info = Ast0.get_info x in
+ let info =
+ match start_line with
+ Some x -> {old_info with Ast0.line_start = x; Ast0.line_end = x}
+ | None -> old_info in
+ {x with Ast0.info = info; Ast0.index = ref(Ast0.get_index x);
+ Ast0.mcodekind = ref (copy_mcodekind (Ast0.get_mcodekind x))} in
+
+ let donothing r k e = copy_one (k e) in
+
+ (* case for control operators (if, etc) *)
+ let statement r k e =
+ let s = k e in
+ let res =
+ copy_one
+ (Ast0.rewrap s
+ (match Ast0.unwrap s with
+ Ast0.Decl((info,mc),decl) ->
+ Ast0.Decl((info,copy_mcodekind mc),decl)
+ | Ast0.IfThen(iff,lp,tst,rp,branch,(info,mc)) ->
+ Ast0.IfThen(iff,lp,tst,rp,branch,(info,copy_mcodekind mc))
+ | Ast0.IfThenElse(iff,lp,tst,rp,branch1,els,branch2,(info,mc)) ->
+ Ast0.IfThenElse(iff,lp,tst,rp,branch1,els,branch2,
+ (info,copy_mcodekind mc))
+ | Ast0.While(whl,lp,exp,rp,body,(info,mc)) ->
+ Ast0.While(whl,lp,exp,rp,body,(info,copy_mcodekind mc))
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,mc)) ->
+ Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,
+ (info,copy_mcodekind mc))
+ | Ast0.Iterator(nm,lp,args,rp,body,(info,mc)) ->
+ Ast0.Iterator(nm,lp,args,rp,body,(info,copy_mcodekind mc))
+ | Ast0.FunDecl
+ ((info,mc),fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ Ast0.FunDecl
+ ((info,copy_mcodekind mc),
+ fninfo,name,lp,params,rp,lbrace,body,rbrace)
+ | s -> s)) in
+ Ast0.set_dots_bef_aft res
+ (match Ast0.get_dots_bef_aft res with
+ Ast0.NoDots -> Ast0.NoDots
+ | Ast0.AddingBetweenDots s ->
+ Ast0.AddingBetweenDots(r.V0.rebuilder_statement s)
+ | Ast0.DroppingBetweenDots s ->
+ Ast0.DroppingBetweenDots(r.V0.rebuilder_statement s)) in
+
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing
+ donothing statement donothing donothing
+
+(* --------------------------------------------------------------------- *)
+(* The problem of whencode. If an isomorphism contains dots in multiple
+ rules, then the code that is matched cannot contain whencode, because we
+ won't know which dots it goes with. Should worry about nests, but they
+ aren't allowed in isomorphisms for the moment. *)
+
+let count_edots =
+ let mcode x = 0 in
+ let option_default = 0 in
+ let bind x y = x + y in
+ let donothing r k e = k e in
+ let exprfn r k e =
+ match Ast0.unwrap e with
+ Ast0.Edots(_,_) | Ast0.Ecircles(_,_) | Ast0.Estars(_,_) -> 1
+ | _ -> 0 in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing exprfn donothing donothing donothing donothing donothing
+ donothing donothing
+
+let count_idots =
+ let mcode x = 0 in
+ let option_default = 0 in
+ let bind x y = x + y in
+ let donothing r k e = k e in
+ let initfn r k e =
+ match Ast0.unwrap e with Ast0.Idots(_,_) -> 1 | _ -> 0 in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing initfn donothing donothing donothing
+ donothing donothing
+
+let count_dots =
+ let mcode x = 0 in
+ let option_default = 0 in
+ let bind x y = x + y in
+ let donothing r k e = k e in
+ let stmtfn r k e =
+ match Ast0.unwrap e with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_) -> 1
+ | _ -> 0 in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing stmtfn
+ donothing donothing
+
+(* --------------------------------------------------------------------- *)
+
+let lookup name bindings mv_bindings =
+ try Common.Left (List.assoc (term name) bindings)
+ with
+ Not_found ->
+ (* failure is not possible anymore *)
+ Common.Right (List.assoc (term name) mv_bindings)
+
+(* mv_bindings is for the fresh metavariables that are introduced by the
+isomorphism *)
+let instantiate bindings mv_bindings =
+ let mcode x =
+ match Ast0.get_pos x with
+ Ast0.MetaPos(name,_,_) ->
+ (try
+ match lookup name bindings mv_bindings with
+ Common.Left(Ast0.MetaPosTag(id)) -> Ast0.set_pos id x
+ | _ -> failwith "not possible"
+ with Not_found -> Ast0.set_pos Ast0.NoMetaPos x)
+ | _ -> x in
+ let donothing r k e = k e in
+
+ (* cases where metavariables can occur *)
+ let identfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaId(name,constraints,pure) ->
+ (rebuild_mcode None).V0.rebuilder_ident
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.IdentTag(id)) -> id
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaId
+ (Ast0.set_mcode_data new_mv name,constraints,pure)))
+ | Ast0.MetaFunc(name,_,pure) -> failwith "metafunc not supported"
+ | Ast0.MetaLocalFunc(name,_,pure) -> failwith "metalocalfunc not supported"
+ | _ -> e in
+
+ (* case for list metavariables *)
+ let rec elist r same_dots = function
+ [] -> []
+ | [x] ->
+ (match Ast0.unwrap x with
+ Ast0.MetaExprList(name,lenname,pure) ->
+ failwith "meta_expr_list in iso not supported"
+ (*match lookup name bindings mv_bindings with
+ Common.Left(Ast0.DotsExprTag(exp)) ->
+ (match same_dots exp with
+ Some l -> l
+ | None -> failwith "dots put in incompatible context")
+ | Common.Left(Ast0.ExprTag(exp)) -> [exp]
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ failwith "MetaExprList in SP not supported"*)
+ | _ -> [r.V0.rebuilder_expression x])
+ | x::xs -> (r.V0.rebuilder_expression x)::(elist r same_dots xs) in
+
+ let rec plist r same_dots = function
+ [] -> []
+ | [x] ->
+ (match Ast0.unwrap x with
+ Ast0.MetaParamList(name,lenname,pure) ->
+ failwith "meta_param_list in iso not supported"
+ (*match lookup name bindings mv_bindings with
+ Common.Left(Ast0.DotsParamTag(param)) ->
+ (match same_dots param with
+ Some l -> l
+ | None -> failwith "dots put in incompatible context")
+ | Common.Left(Ast0.ParamTag(param)) -> [param]
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ failwith "MetaExprList in SP not supported"*)
+ | _ -> [r.V0.rebuilder_parameter x])
+ | x::xs -> (r.V0.rebuilder_parameter x)::(plist r same_dots xs) in
+
+ let rec slist r same_dots = function
+ [] -> []
+ | [x] ->
+ (match Ast0.unwrap x with
+ Ast0.MetaStmtList(name,pure) ->
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.DotsStmtTag(stm)) ->
+ (match same_dots stm with
+ Some l -> l
+ | None -> failwith "dots put in incompatible context")
+ | Common.Left(Ast0.StmtTag(stm)) -> [stm]
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ failwith "MetaExprList in SP not supported")
+ | _ -> [r.V0.rebuilder_statement x])
+ | x::xs -> (r.V0.rebuilder_statement x)::(slist r same_dots xs) in
+
+ let same_dots d =
+ match Ast0.unwrap d with Ast0.DOTS(l) -> Some l |_ -> None in
+ let same_circles d =
+ match Ast0.unwrap d with Ast0.CIRCLES(l) -> Some l |_ -> None in
+ let same_stars d =
+ match Ast0.unwrap d with Ast0.STARS(l) -> Some l |_ -> None in
+
+ let dots list_fn r k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(list_fn r same_dots l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(list_fn r same_circles l)
+ | Ast0.STARS(l) -> Ast0.STARS(list_fn r same_stars l)) in
+
+ let exprfn r k old_e = (* need to keep the original code for ! optim *)
+ let e = k old_e in
+ let e1 =
+ match Ast0.unwrap e with
+ Ast0.MetaExpr(name,constraints,x,form,pure) ->
+ (rebuild_mcode None).V0.rebuilder_expression
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.ExprTag(exp)) -> exp
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ let new_types =
+ match x with
+ None -> None
+ | Some types ->
+ let rec renamer = function
+ Type_cocci.MetaType(name,keep,inherited) ->
+ (match
+ lookup (name,(),(),(),None) bindings mv_bindings
+ with
+ Common.Left(Ast0.TypeCTag(t)) ->
+ Ast0.ast0_type_to_type t
+ | Common.Left(_) ->
+ failwith "iso pattern: unexpected type"
+ | Common.Right(new_mv) ->
+ Type_cocci.MetaType(new_mv,keep,inherited))
+ | Type_cocci.ConstVol(cv,ty) ->
+ Type_cocci.ConstVol(cv,renamer ty)
+ | Type_cocci.Pointer(ty) ->
+ Type_cocci.Pointer(renamer ty)
+ | Type_cocci.FunctionPointer(ty) ->
+ Type_cocci.FunctionPointer(renamer ty)
+ | Type_cocci.Array(ty) ->
+ Type_cocci.Array(renamer ty)
+ | t -> t in
+ Some(List.map renamer types) in
+ Ast0.rewrap e
+ (Ast0.MetaExpr
+ (Ast0.set_mcode_data new_mv name,constraints,
+ new_types,form,pure)))
+ | Ast0.MetaErr(namea,_,pure) -> failwith "metaerr not supported"
+ | Ast0.MetaExprList(namea,lenname,pure) ->
+ failwith "metaexprlist not supported"
+ | Ast0.Unary(exp,unop) ->
+ (match Ast0.unwrap_mcode unop with
+ Ast.Not ->
+ let was_meta =
+ (* k e doesn't change the outer structure of the term,
+ only the metavars *)
+ match Ast0.unwrap old_e with
+ Ast0.Unary(exp,_) ->
+ (match Ast0.unwrap exp with
+ Ast0.MetaExpr(name,constraints,x,form,pure) -> true
+ | _ -> false)
+ | _ -> failwith "not possible" in
+ let nomodif e =
+ let mc = Ast0.get_mcodekind exp in
+ match mc with
+ Ast0.MINUS(x) ->
+ (match !x with
+ ([],_) -> true
+ | _ -> false)
+ | Ast0.CONTEXT(x) | Ast0.MIXED(x) ->
+ (match !x with
+ (Ast.NOTHING,_,_) -> true
+ | _ -> false)
+ | _ -> failwith "plus not possible" in
+ if was_meta && nomodif exp && nomodif e
+ then
+ let rec negate e (*for rewrapping*) res (*code to process*) =
+ match Ast0.unwrap res with
+ Ast0.Unary(e1,op) when Ast0.unwrap_mcode op = Ast.Not ->
+ Ast0.rewrap e (Ast0.unwrap e1)
+ | Ast0.Edots(_,_) -> Ast0.rewrap e (Ast0.unwrap res)
+ | Ast0.Paren(lp,e,rp) ->
+ Ast0.rewrap res (Ast0.Paren(lp,negate e e,rp))
+ | Ast0.Binary(e1,op,e2) ->
+ let reb nop = Ast0.rewrap_mcode op (Ast.Logical(nop)) in
+ let invop =
+ match Ast0.unwrap_mcode op with
+ Ast.Logical(Ast.Inf) ->
+ Ast0.Binary(e1,reb Ast.SupEq,e2)
+ | Ast.Logical(Ast.Sup) ->
+ Ast0.Binary(e1,reb Ast.InfEq,e2)
+ | Ast.Logical(Ast.InfEq) ->
+ Ast0.Binary(e1,reb Ast.Sup,e2)
+ | Ast.Logical(Ast.SupEq) ->
+ Ast0.Binary(e1,reb Ast.Inf,e2)
+ | Ast.Logical(Ast.Eq) ->
+ Ast0.Binary(e1,reb Ast.NotEq,e2)
+ | Ast.Logical(Ast.NotEq) ->
+ Ast0.Binary(e1,reb Ast.Eq,e2)
+ | Ast.Logical(Ast.AndLog) ->
+ Ast0.Binary(negate e1 e1,reb Ast.OrLog,
+ negate e2 e2)
+ | Ast.Logical(Ast.OrLog) ->
+ Ast0.Binary(negate e1 e1,reb Ast.AndLog,
+ negate e2 e2)
+ | _ -> Ast0.Unary(res,Ast0.rewrap_mcode op Ast.Not) in
+ Ast0.rewrap e invop
+ | Ast0.DisjExpr(lp,exps,mids,rp) ->
+ (* use res because it is the transformed argument *)
+ let exps = List.map (function e -> negate e e) exps in
+ Ast0.rewrap res (Ast0.DisjExpr(lp,exps,mids,rp))
+ | _ ->
+ (*use e, because this might be the toplevel expression*)
+ Ast0.rewrap e
+ (Ast0.Unary(res,Ast0.rewrap_mcode unop Ast.Not)) in
+ negate e exp
+ else e
+ | _ -> e)
+ | Ast0.Edots(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.ExprTag(exp) -> Ast0.rewrap e (Ast0.Edots(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | Ast0.Ecircles(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.ExprTag(exp) -> Ast0.rewrap e (Ast0.Ecircles(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | Ast0.Estars(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.ExprTag(exp) -> Ast0.rewrap e (Ast0.Estars(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | _ -> e in
+ if Ast0.get_test_exp old_e then Ast0.set_test_exp e1 else e1 in
+
+ let tyfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaType(name,pure) ->
+ (rebuild_mcode None).V0.rebuilder_typeC
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.TypeCTag(ty)) -> ty
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaType(Ast0.set_mcode_data new_mv name,pure)))
+ | _ -> e in
+
+ let declfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.Ddots(d,_) ->
+ (try
+ (match List.assoc (dot_term d) bindings with
+ Ast0.DeclTag(exp) -> Ast0.rewrap e (Ast0.Ddots(d,Some exp))
+ | _ -> failwith "unexpected binding")
+ with Not_found -> e)
+ | _ -> e in
+
+ let paramfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaParam(name,pure) ->
+ (rebuild_mcode None).V0.rebuilder_parameter
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.ParamTag(param)) -> param
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaParam(Ast0.set_mcode_data new_mv name, pure)))
+ | Ast0.MetaParamList(name,lenname,pure) ->
+ failwith "metaparamlist not supported"
+ | _ -> e in
+
+ let whenfn (_,v) =
+ match v with
+ Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
+ | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
+ | Ast0.IsoWhenTTag(stm) -> Ast0.WhenNotTrue stm
+ | Ast0.IsoWhenFTag(stm) -> Ast0.WhenNotFalse stm
+ | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
+ | _ -> failwith "unexpected binding" in
+
+ let stmtfn r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.MetaStmt(name,pure) ->
+ (rebuild_mcode None).V0.rebuilder_statement
+ (match lookup name bindings mv_bindings with
+ Common.Left(Ast0.StmtTag(stm)) -> stm
+ | Common.Left(_) -> failwith "not possible 1"
+ | Common.Right(new_mv) ->
+ Ast0.rewrap e
+ (Ast0.MetaStmt(Ast0.set_mcode_data new_mv name,pure)))
+ | Ast0.MetaStmtList(name,pure) -> failwith "metastmtlist not supported"
+ | Ast0.Dots(d,_) ->
+ Ast0.rewrap e
+ (Ast0.Dots
+ (d,
+ List.map whenfn
+ (List.filter (function (x,v) -> x = (dot_term d)) bindings)))
+ | Ast0.Circles(d,_) ->
+ Ast0.rewrap e
+ (Ast0.Circles
+ (d,
+ List.map whenfn
+ (List.filter (function (x,v) -> x = (dot_term d)) bindings)))
+ | Ast0.Stars(d,_) ->
+ Ast0.rewrap e
+ (Ast0.Stars
+ (d,
+ List.map whenfn
+ (List.filter (function (x,v) -> x = (dot_term d)) bindings)))
+ | _ -> e in
+
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ (dots elist) donothing (dots plist) (dots slist) donothing donothing
+ identfn exprfn tyfn donothing paramfn declfn stmtfn donothing donothing
+
+(* --------------------------------------------------------------------- *)
+
+let is_minus e =
+ match Ast0.get_mcodekind e with Ast0.MINUS(cell) -> true | _ -> false
+
+let context_required e = not(is_minus e) && not !Flag.sgrep_mode2
+
+let disj_fail bindings e =
+ match bindings with
+ Some x -> Printf.fprintf stderr "no disj available at this type"; e
+ | None -> e
+
+(* isomorphism code is by default CONTEXT *)
+let merge_plus model_mcode e_mcode =
+ match model_mcode with
+ Ast0.MINUS(mc) ->
+ (* add the replacement information at the root *)
+ (match e_mcode with
+ Ast0.MINUS(emc) ->
+ emc :=
+ (match (!mc,!emc) with
+ (([],_),(x,t)) | ((x,_),([],t)) -> (x,t)
+ | _ -> failwith "how can we combine minuses?")
+ | _ -> failwith "not possible 6")
+ | Ast0.CONTEXT(mc) ->
+ (match e_mcode with
+ Ast0.CONTEXT(emc) ->
+ (* keep the logical line info as in the model *)
+ let (mba,tb,ta) = !mc in
+ let (eba,_,_) = !emc in
+ (* merging may be required when a term is replaced by a subterm *)
+ let merged =
+ match (mba,eba) with
+ (x,Ast.NOTHING) | (Ast.NOTHING,x) -> x
+ | (Ast.BEFORE(b1),Ast.BEFORE(b2)) -> Ast.BEFORE(b1@b2)
+ | (Ast.BEFORE(b),Ast.AFTER(a)) -> Ast.BEFOREAFTER(b,a)
+ | (Ast.BEFORE(b1),Ast.BEFOREAFTER(b2,a)) ->
+ Ast.BEFOREAFTER(b1@b2,a)
+ | (Ast.AFTER(a),Ast.BEFORE(b)) -> Ast.BEFOREAFTER(b,a)
+ | (Ast.AFTER(a1),Ast.AFTER(a2)) ->Ast.AFTER(a2@a1)
+ | (Ast.AFTER(a1),Ast.BEFOREAFTER(b,a2)) -> Ast.BEFOREAFTER(b,a2@a1)
+ | (Ast.BEFOREAFTER(b1,a),Ast.BEFORE(b2)) ->
+ Ast.BEFOREAFTER(b1@b2,a)
+ | (Ast.BEFOREAFTER(b,a1),Ast.AFTER(a2)) ->
+ Ast.BEFOREAFTER(b,a2@a1)
+ | (Ast.BEFOREAFTER(b1,a1),Ast.BEFOREAFTER(b2,a2)) ->
+ Ast.BEFOREAFTER(b1@b2,a2@a1) in
+ emc := (merged,tb,ta)
+ | Ast0.MINUS(emc) ->
+ let (anything_bef_aft,_,_) = !mc in
+ let (anythings,t) = !emc in
+ emc :=
+ (match anything_bef_aft with
+ Ast.BEFORE(b) -> (b@anythings,t)
+ | Ast.AFTER(a) -> (anythings@a,t)
+ | Ast.BEFOREAFTER(b,a) -> (b@anythings@a,t)
+ | Ast.NOTHING -> (anythings,t))
+ | _ -> failwith "not possible 7")
+ | Ast0.MIXED(_) -> failwith "not possible 8"
+ | Ast0.PLUS -> failwith "not possible 9"
+
+let copy_plus printer minusify model e =
+ if !Flag.sgrep_mode2
+ then e (* no plus code, can cause a "not possible" error, so just avoid it *)
+ else
+ let e =
+ match Ast0.get_mcodekind model with
+ Ast0.MINUS(mc) -> minusify e
+ | Ast0.CONTEXT(mc) -> e
+ | _ -> failwith "not possible: copy_plus\n" in
+ merge_plus (Ast0.get_mcodekind model) (Ast0.get_mcodekind e);
+ e
+
+let copy_minus printer minusify model e =
+ match Ast0.get_mcodekind model with
+ Ast0.MINUS(mc) -> minusify e
+ | Ast0.CONTEXT(mc) -> e
+ | Ast0.MIXED(_) ->
+ if !Flag.sgrep_mode2
+ then e
+ else failwith "not possible 8"
+ | Ast0.PLUS -> failwith "not possible 9"
+
+let whencode_allowed prev_ecount prev_icount prev_dcount
+ ecount icount dcount rest =
+ (* actually, if ecount or dcount is 0, the flag doesn't matter, because it
+ won't be tested *)
+ let other_ecount = (* number of edots *)
+ List.fold_left (function rest -> function (_,ec,ic,dc) -> ec + rest)
+ prev_ecount rest in
+ let other_icount = (* number of dots *)
+ List.fold_left (function rest -> function (_,ec,ic,dc) -> ic + rest)
+ prev_icount rest in
+ let other_dcount = (* number of dots *)
+ List.fold_left (function rest -> function (_,ec,ic,dc) -> dc + rest)
+ prev_dcount rest in
+ (ecount = 0 or other_ecount = 0, icount = 0 or other_icount = 0,
+ dcount = 0 or other_dcount = 0)
+
+(* copy the befores and afters to the instantiated code *)
+let extra_copy_stmt_plus model e =
+ (if not !Flag.sgrep_mode2 (* sgrep has no plus code, so nothing to do *)
+ then
+ (match Ast0.unwrap model with
+ Ast0.FunDecl((info,bef),_,_,_,_,_,_,_,_)
+ | Ast0.Decl((info,bef),_) ->
+ (match Ast0.unwrap e with
+ Ast0.FunDecl((info,bef1),_,_,_,_,_,_,_,_)
+ | Ast0.Decl((info,bef1),_) ->
+ merge_plus bef bef1
+ | _ -> merge_plus bef (Ast0.get_mcodekind e))
+ | Ast0.IfThen(_,_,_,_,_,(info,aft))
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft))
+ | Ast0.While(_,_,_,_,_,(info,aft))
+ | Ast0.For(_,_,_,_,_,_,_,_,_,(info,aft))
+ | Ast0.Iterator(_,_,_,_,_,(info,aft)) ->
+ (match Ast0.unwrap e with
+ Ast0.IfThen(_,_,_,_,_,(info,aft1))
+ | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft1))
+ | Ast0.While(_,_,_,_,_,(info,aft1))
+ | Ast0.For(_,_,_,_,_,_,_,_,_,(info,aft1))
+ | Ast0.Iterator(_,_,_,_,_,(info,aft1)) ->
+ merge_plus aft aft1
+ | _ -> merge_plus aft (Ast0.get_mcodekind e))
+ | _ -> ()));
+ e
+
+let extra_copy_other_plus model e = e
+
+(* --------------------------------------------------------------------- *)
+
+let mv_count = ref 0
+let new_mv (_,s) =
+ let ct = !mv_count in
+ mv_count := !mv_count + 1;
+ "_"^s^"_"^(string_of_int ct)
+
+let get_name = function
+ Ast.MetaIdDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaIdDecl(ar,nm))
+ | Ast.MetaFreshIdDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaFreshIdDecl(ar,nm))
+ | Ast.MetaTypeDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaTypeDecl(ar,nm))
+ | Ast.MetaListlenDecl(nm) ->
+ failwith "should not be rebuilt"
+ | Ast.MetaParamDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaParamDecl(ar,nm))
+ | Ast.MetaParamListDecl(ar,nm,nm1) ->
+ (nm,function nm -> Ast.MetaParamListDecl(ar,nm,nm1))
+ | Ast.MetaConstDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaConstDecl(ar,nm,ty))
+ | Ast.MetaErrDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaErrDecl(ar,nm))
+ | Ast.MetaExpDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaExpDecl(ar,nm,ty))
+ | Ast.MetaIdExpDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaIdExpDecl(ar,nm,ty))
+ | Ast.MetaLocalIdExpDecl(ar,nm,ty) ->
+ (nm,function nm -> Ast.MetaLocalIdExpDecl(ar,nm,ty))
+ | Ast.MetaExpListDecl(ar,nm,nm1) ->
+ (nm,function nm -> Ast.MetaExpListDecl(ar,nm,nm1))
+ | Ast.MetaStmDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaStmDecl(ar,nm))
+ | Ast.MetaStmListDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaStmListDecl(ar,nm))
+ | Ast.MetaFuncDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaFuncDecl(ar,nm))
+ | Ast.MetaLocalFuncDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaLocalFuncDecl(ar,nm))
+ | Ast.MetaPosDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaPosDecl(ar,nm))
+ | Ast.MetaDeclarerDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaDeclarerDecl(ar,nm))
+ | Ast.MetaIteratorDecl(ar,nm) ->
+ (nm,function nm -> Ast.MetaIteratorDecl(ar,nm))
+
+let make_new_metavars metavars bindings =
+ let new_metavars =
+ List.filter
+ (function mv ->
+ let (s,_) = get_name mv in
+ try let _ = List.assoc s bindings in false with Not_found -> true)
+ metavars in
+ List.split
+ (List.map
+ (function mv ->
+ let (s,rebuild) = get_name mv in
+ let new_s = (!current_rule,new_mv s) in
+ (rebuild new_s, (s,new_s)))
+ new_metavars)
+
+(* --------------------------------------------------------------------- *)
+
+let do_nothing x = x
+
+let mkdisj matcher metavars alts e instantiater mkiso disj_maker minusify
+ rebuild_mcodes name printer extra_plus update_others =
+ let call_instantiate bindings mv_bindings alts =
+ List.concat
+ (List.map
+ (function (a,_,_,_) ->
+ nub
+ (* no need to create duplicates when the bindings have no effect *)
+ (List.map
+ (function bindings ->
+ Ast0.set_iso
+ (copy_plus printer minusify e
+ (extra_plus e
+ (instantiater bindings mv_bindings
+ (rebuild_mcodes a))))
+ (Common.union_set [(name,mkiso a)] (Ast0.get_iso e)))
+ bindings))
+ alts) in
+ let rec inner_loop all_alts prev_ecount prev_icount prev_dcount = function
+ [] -> Common.Left (prev_ecount, prev_icount, prev_dcount)
+ | ((pattern,ecount,icount,dcount)::rest) ->
+ let wc =
+ whencode_allowed prev_ecount prev_icount prev_dcount
+ ecount dcount icount rest in
+ (match matcher true (context_required e) wc pattern e init_env with
+ Fail(reason) ->
+ if reason = NonMatch || not !Flag_parsing_cocci.show_iso_failures
+ then ()
+ else
+ (match matcher false false wc pattern e init_env with
+ OK _ ->
+ interpret_reason name (Ast0.get_line e) reason
+ (function () -> printer e)
+ | _ -> ());
+ inner_loop all_alts (prev_ecount + ecount) (prev_icount + icount)
+ (prev_dcount + dcount) rest
+ | OK (bindings : (((string * string) * 'a) list list)) ->
+ let all_alts =
+ (* apply update_others to all patterns other than the matched
+ one. This is used to desigate the others as test
+ expressions in the TestExpression case *)
+ (List.map
+ (function (x,e,i,d) as all ->
+ if x = pattern
+ then all
+ else (update_others x,e,i,d))
+ (List.hd all_alts)) ::
+ (List.map
+ (List.map (function (x,e,i,d) -> (update_others x,e,i,d)))
+ (List.tl all_alts)) in
+ (match List.concat all_alts with
+ [x] -> Common.Left (prev_ecount, prev_icount, prev_dcount)
+ | all_alts ->
+ let (new_metavars,mv_bindings) =
+ make_new_metavars metavars (nub(List.concat bindings)) in
+ Common.Right
+ (new_metavars,
+ call_instantiate bindings mv_bindings all_alts))) in
+ let rec outer_loop prev_ecount prev_icount prev_dcount = function
+ [] | [[_]] (*only one alternative*) -> ([],e) (* nothing matched *)
+ | (alts::rest) as all_alts ->
+ match inner_loop all_alts prev_ecount prev_icount prev_dcount alts with
+ Common.Left(prev_ecount, prev_icount, prev_dcount) ->
+ outer_loop prev_ecount prev_icount prev_dcount rest
+ | Common.Right (new_metavars,res) ->
+ (new_metavars,
+ copy_minus printer minusify e (disj_maker res)) in
+ outer_loop 0 0 0 alts
+
+(* no one should ever look at the information stored in these mcodes *)
+let disj_starter lst =
+ let old_info = Ast0.get_info(List.hd lst) in
+ let info =
+ { old_info with
+ Ast0.line_end = old_info.Ast0.line_start;
+ Ast0.logical_end = old_info.Ast0.logical_start;
+ Ast0.attachable_start = false; Ast0.attachable_end = false;
+ Ast0.mcode_start = []; Ast0.mcode_end = [];
+ Ast0.strings_before = []; Ast0.strings_after = [] } in
+ Ast0.make_mcode_info "(" info
+
+let disj_ender lst =
+ let old_info = Ast0.get_info(List.hd lst) in
+ let info =
+ { old_info with
+ Ast0.line_start = old_info.Ast0.line_end;
+ Ast0.logical_start = old_info.Ast0.logical_end;
+ Ast0.attachable_start = false; Ast0.attachable_end = false;
+ Ast0.mcode_start = []; Ast0.mcode_end = [];
+ Ast0.strings_before = []; Ast0.strings_after = [] } in
+ Ast0.make_mcode_info ")" info
+
+let disj_mid _ = Ast0.make_mcode "|"
+
+let make_disj_type tl =
+ let mids =
+ match tl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap (Ast0.DisjType(disj_starter tl,tl,mids,disj_ender tl))
+let make_disj_stmt_list tl =
+ let mids =
+ match tl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap (Ast0.Disj(disj_starter tl,tl,mids,disj_ender tl))
+let make_disj_expr model el =
+ let mids =
+ match el with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ let update_arg x =
+ if Ast0.get_arg_exp model then Ast0.set_arg_exp x else x in
+ let update_test x =
+ let x = if Ast0.get_test_pos model then Ast0.set_test_pos x else x in
+ if Ast0.get_test_exp model then Ast0.set_test_exp x else x in
+ let el = List.map update_arg (List.map update_test el) in
+ Ast0.context_wrap (Ast0.DisjExpr(disj_starter el,el,mids,disj_ender el))
+let make_disj_decl dl =
+ let mids =
+ match dl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap (Ast0.DisjDecl(disj_starter dl,dl,mids,disj_ender dl))
+let make_disj_stmt sl =
+ let dotify x = Ast0.context_wrap (Ast0.DOTS[x]) in
+ let mids =
+ match sl with
+ [] -> failwith "bad disjunction"
+ | x::xs -> List.map disj_mid xs in
+ Ast0.context_wrap
+ (Ast0.Disj(disj_starter sl,List.map dotify sl,mids,disj_ender sl))
+
+let transform_type (metavars,alts,name) e =
+ match alts with
+ (Ast0.TypeCTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some ((Ast0.get_info e).Ast0.line_start) in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.TypeCTag(p) ->
+ (p,count_edots.V0.combiner_typeC p,
+ count_idots.V0.combiner_typeC p,
+ count_dots.V0.combiner_typeC p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_typeC metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_typeC)
+ (function t -> Ast0.TypeCTag t)
+ make_disj_type make_minus.V0.rebuilder_typeC
+ (rebuild_mcode start_line).V0.rebuilder_typeC
+ name Unparse_ast0.typeC extra_copy_other_plus do_nothing
+ | _ -> ([],e)
+
+
+let transform_expr (metavars,alts,name) e =
+ let process update_others =
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some ((Ast0.get_info e).Ast0.line_start) in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.ExprTag(p) | Ast0.ArgExprTag(p) | Ast0.TestExprTag(p) ->
+ (p,count_edots.V0.combiner_expression p,
+ count_idots.V0.combiner_expression p,
+ count_dots.V0.combiner_expression p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_expr metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_expression)
+ (function e -> Ast0.ExprTag e)
+ (make_disj_expr e) make_minus.V0.rebuilder_expression
+ (rebuild_mcode start_line).V0.rebuilder_expression
+ name Unparse_ast0.expression extra_copy_other_plus update_others in
+ match alts with
+ (Ast0.ExprTag(_)::_)::_ -> process do_nothing
+ | (Ast0.ArgExprTag(_)::_)::_ when Ast0.get_arg_exp e -> process do_nothing
+ | (Ast0.TestExprTag(_)::_)::_ when Ast0.get_test_pos e ->
+ process Ast0.set_test_exp
+ | _ -> ([],e)
+
+let transform_decl (metavars,alts,name) e =
+ match alts with
+ (Ast0.DeclTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some (Ast0.get_info e).Ast0.line_start in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.DeclTag(p) ->
+ (p,count_edots.V0.combiner_declaration p,
+ count_idots.V0.combiner_declaration p,
+ count_dots.V0.combiner_declaration p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_decl metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_declaration)
+ (function d -> Ast0.DeclTag d)
+ make_disj_decl
+ make_minus.V0.rebuilder_declaration
+ (rebuild_mcode start_line).V0.rebuilder_declaration
+ name Unparse_ast0.declaration extra_copy_other_plus do_nothing
+ | _ -> ([],e)
+
+let transform_stmt (metavars,alts,name) e =
+ match alts with
+ (Ast0.StmtTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some (Ast0.get_info e).Ast0.line_start in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.StmtTag(p) ->
+ (p,count_edots.V0.combiner_statement p,
+ count_idots.V0.combiner_statement p,
+ count_dots.V0.combiner_statement p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_statement metavars alts e
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_statement)
+ (function s -> Ast0.StmtTag s)
+ make_disj_stmt make_minus.V0.rebuilder_statement
+ (rebuild_mcode start_line).V0.rebuilder_statement
+ name (Unparse_ast0.statement "") extra_copy_stmt_plus do_nothing
+ | _ -> ([],e)
+
+(* sort of a hack, because there is no disj at top level *)
+let transform_top (metavars,alts,name) e =
+ match Ast0.unwrap e with
+ Ast0.DECL(declstm) ->
+ (try
+ let strip alts =
+ List.map
+ (List.map
+ (function
+ Ast0.DotsStmtTag(d) ->
+ (match Ast0.unwrap d with
+ Ast0.DOTS([s]) -> Ast0.StmtTag(s)
+ | _ -> raise (Failure ""))
+ | _ -> raise (Failure "")))
+ alts in
+ let (mv,s) = transform_stmt (metavars,strip alts,name) declstm in
+ (mv,Ast0.rewrap e (Ast0.DECL(s)))
+ with Failure _ -> ([],e))
+ | Ast0.CODE(stmts) ->
+ let (mv,res) =
+ match alts with
+ (Ast0.DotsStmtTag(_)::_)::_ ->
+ (* start line is given to any leaves in the iso code *)
+ let start_line = Some ((Ast0.get_info e).Ast0.line_start) in
+ let alts =
+ List.map
+ (List.map
+ (function
+ Ast0.DotsStmtTag(p) ->
+ (p,count_edots.V0.combiner_statement_dots p,
+ count_idots.V0.combiner_statement_dots p,
+ count_dots.V0.combiner_statement_dots p)
+ | _ -> failwith "invalid alt"))
+ alts in
+ mkdisj match_statement_dots metavars alts stmts
+ (function b -> function mv_b ->
+ (instantiate b mv_b).V0.rebuilder_statement_dots)
+ (function s -> Ast0.DotsStmtTag s)
+ (function x ->
+ Ast0.rewrap e (Ast0.DOTS([make_disj_stmt_list x])))
+ make_minus.V0.rebuilder_statement_dots
+ (rebuild_mcode start_line).V0.rebuilder_statement_dots
+ name Unparse_ast0.statement_dots extra_copy_other_plus do_nothing
+ | _ -> ([],stmts) in
+ (mv,Ast0.rewrap e (Ast0.CODE res))
+ | _ -> ([],e)
+
+(* --------------------------------------------------------------------- *)
+
+let transform (alts : isomorphism) t =
+ (* the following ugliness is because rebuilder only returns a new term *)
+ let extra_meta_decls = ref ([] : Ast_cocci.metavar list) in
+ let mcode x = x in
+ let donothing r k e = k e in
+ let exprfn r k e =
+ let (extra_meta,exp) = transform_expr alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ exp in
+
+ let declfn r k e =
+ let (extra_meta,dec) = transform_decl alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ dec in
+
+ let stmtfn r k e =
+ let (extra_meta,stm) = transform_stmt alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ stm in
+
+ let typefn r k e =
+ let (extra_meta,ty) = transform_type alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ ty in
+
+ let topfn r k e =
+ let (extra_meta,ty) = transform_top alts (k e) in
+ extra_meta_decls := extra_meta @ !extra_meta_decls;
+ ty in
+
+ let res =
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing exprfn typefn donothing donothing declfn stmtfn
+ donothing topfn in
+ let res = res.V0.rebuilder_top_level t in
+ (!extra_meta_decls,res)
+
+(* --------------------------------------------------------------------- *)
+
+(* should be done by functorizing the parser to use wrap or context_wrap *)
+let rewrap =
+ let mcode (x,a,i,mc,pos) = (x,a,i,Ast0.context_befaft(),pos) in
+ let donothing r k e = Ast0.context_wrap(Ast0.unwrap(k e)) in
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing
+
+let rewrap_anything = function
+ Ast0.DotsExprTag(d) ->
+ Ast0.DotsExprTag(rewrap.V0.rebuilder_expression_dots d)
+ | Ast0.DotsInitTag(d) ->
+ Ast0.DotsInitTag(rewrap.V0.rebuilder_initialiser_list d)
+ | Ast0.DotsParamTag(d) ->
+ Ast0.DotsParamTag(rewrap.V0.rebuilder_parameter_list d)
+ | Ast0.DotsStmtTag(d) ->
+ Ast0.DotsStmtTag(rewrap.V0.rebuilder_statement_dots d)
+ | Ast0.DotsDeclTag(d) ->
+ Ast0.DotsDeclTag(rewrap.V0.rebuilder_declaration_dots d)
+ | Ast0.DotsCaseTag(d) ->
+ Ast0.DotsCaseTag(rewrap.V0.rebuilder_case_line_dots d)
+ | Ast0.IdentTag(d) -> Ast0.IdentTag(rewrap.V0.rebuilder_ident d)
+ | Ast0.ExprTag(d) -> Ast0.ExprTag(rewrap.V0.rebuilder_expression d)
+ | Ast0.ArgExprTag(d) -> Ast0.ArgExprTag(rewrap.V0.rebuilder_expression d)
+ | Ast0.TestExprTag(d) -> Ast0.TestExprTag(rewrap.V0.rebuilder_expression d)
+ | Ast0.TypeCTag(d) -> Ast0.TypeCTag(rewrap.V0.rebuilder_typeC d)
+ | Ast0.InitTag(d) -> Ast0.InitTag(rewrap.V0.rebuilder_initialiser d)
+ | Ast0.ParamTag(d) -> Ast0.ParamTag(rewrap.V0.rebuilder_parameter d)
+ | Ast0.DeclTag(d) -> Ast0.DeclTag(rewrap.V0.rebuilder_declaration d)
+ | Ast0.StmtTag(d) -> Ast0.StmtTag(rewrap.V0.rebuilder_statement d)
+ | Ast0.CaseLineTag(d) -> Ast0.CaseLineTag(rewrap.V0.rebuilder_case_line d)
+ | Ast0.TopTag(d) -> Ast0.TopTag(rewrap.V0.rebuilder_top_level d)
+ | Ast0.IsoWhenTag(_) | Ast0.IsoWhenTTag(_) | Ast0.IsoWhenFTag(_) ->
+ failwith "only for isos within iso phase"
+ | Ast0.MetaPosTag(p) -> Ast0.MetaPosTag(p)
+
+(* --------------------------------------------------------------------- *)
+
+let apply_isos isos rule rule_name =
+ if isos = []
+ then ([],rule)
+ else
+ begin
+ current_rule := rule_name;
+ let isos =
+ List.map
+ (function (metavars,iso,name) ->
+ (metavars,List.map (List.map rewrap_anything) iso,name))
+ isos in
+ let (extra_meta,rule) =
+ List.split
+ (List.map
+ (function t ->
+ List.fold_left
+ (function (extra_meta,t) -> function iso ->
+ let (new_extra_meta,t) = transform iso t in
+ (new_extra_meta@extra_meta,t))
+ ([],t) isos)
+ rule) in
+ (List.concat extra_meta, Compute_lines.compute_lines rule)
+ end
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+{
+open Parser_cocci_menhir
+module D = Data
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module P = Parse_aux
+exception Lexical of string
+let tok = Lexing.lexeme
+
+let line = ref 1
+let logical_line = ref 0
+
+(* ---------------------------------------------------------------------- *)
+(* control codes *)
+
+(* Defined in data.ml
+type line_type = MINUS | OPTMINUS | UNIQUEMINUS | PLUS | CONTEXT | UNIQUE | OPT
+*)
+
+let current_line_type = ref (D.CONTEXT,!line,!logical_line)
+
+let prev_plus = ref false
+let line_start = ref 0 (* offset of the beginning of the line *)
+let get_current_line_type lexbuf =
+ let (c,l,ll) = !current_line_type in
+ let lex_start = Lexing.lexeme_start lexbuf in
+ let preceeding_spaces =
+ if !line_start < 0 then 0 else lex_start - !line_start in
+ line_start := -1;
+ prev_plus := (c = D.PLUS);
+ (c,l,ll,lex_start,preceeding_spaces,[],[],Ast0.NoMetaPos)
+let current_line_started = ref false
+let col_zero = ref true
+
+let reset_line lexbuf =
+ line := !line + 1;
+ current_line_type := (D.CONTEXT,!line,!logical_line);
+ current_line_started := false;
+ col_zero := true;
+ line_start := Lexing.lexeme_start lexbuf + 1
+
+let started_line = ref (-1)
+
+let start_line seen_char =
+ current_line_started := true;
+ col_zero := false;
+ (if seen_char && not(!line = !started_line)
+ then
+ begin
+ started_line := !line;
+ logical_line := !logical_line + 1
+ end)
+
+let pass_zero _ = col_zero := false
+
+let lexerr s1 s2 = raise (Lexical (Printf.sprintf "%s%s" s1 s2))
+
+let add_current_line_type x =
+ match (x,!current_line_type) with
+ (D.MINUS,(D.CONTEXT,ln,lln)) ->
+ current_line_type := (D.MINUS,ln,lln)
+ | (D.MINUS,(D.UNIQUE,ln,lln)) ->
+ current_line_type := (D.UNIQUEMINUS,ln,lln)
+ | (D.MINUS,(D.OPT,ln,lln)) ->
+ current_line_type := (D.OPTMINUS,ln,lln)
+ | (D.PLUS,(D.CONTEXT,ln,lln)) ->
+ current_line_type := (D.PLUS,ln,lln)
+ | (D.UNIQUE,(D.CONTEXT,ln,lln)) ->
+ current_line_type := (D.UNIQUE,ln,lln)
+ | (D.OPT,(D.CONTEXT,ln,lln)) ->
+ current_line_type := (D.OPT,ln,lln)
+ | _ -> lexerr "invalid control character combination" ""
+
+let check_minus_context_linetype s =
+ match !current_line_type with
+ (D.PLUS,_,_) -> lexerr "invalid in a + context: " s
+ | _ -> ()
+
+let check_context_linetype s =
+ match !current_line_type with
+ (D.CONTEXT,_,_) -> ()
+ | _ -> lexerr "invalid in a nonempty context: " s
+
+let check_plus_linetype s =
+ match !current_line_type with
+ (D.PLUS,_,_) -> ()
+ | _ -> lexerr "invalid in a non + context: " s
+
+let check_arity_context_linetype s =
+ match !current_line_type with
+ (D.CONTEXT,_,_) | (D.PLUS,_,_) | (D.UNIQUE,_,_) | (D.OPT,_,_) -> ()
+ | _ -> lexerr "invalid in a nonempty context: " s
+
+let process_include start finish str =
+ (match !current_line_type with
+ (D.PLUS,_,_) ->
+ (try
+ let _ = Str.search_forward (Str.regexp "\\.\\.\\.") str start in
+ lexerr "... not allowed in + include" ""
+ with Not_found -> ())
+ | _ -> ());
+ String.sub str (start + 1) (finish - start - 1)
+
+(* ---------------------------------------------------------------------- *)
+type pm = PATCH | MATCH | UNKNOWN
+
+let pm = ref UNKNOWN
+
+let patch_or_match = function
+ PATCH ->
+ (match !pm with
+ MATCH -> lexerr "- or + not allowed in the first column for a match" ""
+ | PATCH -> ()
+ | UNKNOWN -> Flag.sgrep_mode2 := false; pm := PATCH)
+ | MATCH ->
+ (match !pm with
+ PATCH -> lexerr "* not allowed in the first column for a patch" ""
+ | MATCH -> ()
+ | UNKNOWN -> Flag.sgrep_mode2 := true; pm := MATCH)
+ | _ -> failwith "unexpected argument"
+
+(* ---------------------------------------------------------------------- *)
+(* identifiers, including metavariables *)
+
+let metavariables = (Hashtbl.create(100) : (string, D.clt -> token) Hashtbl.t)
+
+let all_metavariables =
+ (Hashtbl.create(100) : (string,(string * (D.clt -> token)) list) Hashtbl.t)
+
+let type_names = (Hashtbl.create(100) : (string, D.clt -> token) Hashtbl.t)
+
+let declarer_names = (Hashtbl.create(100) : (string, D.clt -> token) Hashtbl.t)
+
+let iterator_names = (Hashtbl.create(100) : (string, D.clt -> token) Hashtbl.t)
+
+let rule_names = (Hashtbl.create(100) : (string, unit) Hashtbl.t)
+
+let check_var s linetype =
+ let fail _ =
+ if (!Data.in_prolog || !Data.in_rule_name) &&
+ Str.string_match (Str.regexp "<.*>") s 0
+ then TPathIsoFile s
+ else
+ try (Hashtbl.find metavariables s) linetype
+ with Not_found ->
+ (try (Hashtbl.find type_names s) linetype
+ with Not_found ->
+ (try (Hashtbl.find declarer_names s) linetype
+ with Not_found ->
+ (try (Hashtbl.find iterator_names s) linetype
+ with Not_found -> TIdent (s,linetype)))) in
+ if !Data.in_meta or !Data.in_rule_name
+ then (try Hashtbl.find rule_names s; TRuleName s with Not_found -> fail())
+ else fail()
+
+let id_tokens lexbuf =
+ let s = tok lexbuf in
+ let linetype = get_current_line_type lexbuf in
+ let in_rule_name = !Data.in_rule_name in
+ let in_meta = !Data.in_meta in
+ let in_iso = !Data.in_iso in
+ let in_prolog = !Data.in_prolog in
+ match s with
+ "identifier" when in_meta -> check_arity_context_linetype s; TIdentifier
+ | "type" when in_meta -> check_arity_context_linetype s; TType
+ | "parameter" when in_meta -> check_arity_context_linetype s; TParameter
+ | "constant" when in_meta -> check_arity_context_linetype s; TConstant
+ | "expression" when in_meta || in_rule_name ->
+ check_arity_context_linetype s; TExpression
+ | "idexpression" when in_meta ->
+ check_arity_context_linetype s; TIdExpression
+ | "statement" when in_meta -> check_arity_context_linetype s; TStatement
+ | "function" when in_meta -> check_arity_context_linetype s; TFunction
+ | "local" when in_meta -> check_arity_context_linetype s; TLocal
+ | "list" when in_meta -> check_arity_context_linetype s; Tlist
+ | "fresh" when in_meta -> check_arity_context_linetype s; TFresh
+ | "typedef" when in_meta -> check_arity_context_linetype s; TTypedef
+ | "declarer" when in_meta -> check_arity_context_linetype s; TDeclarer
+ | "iterator" when in_meta -> check_arity_context_linetype s; TIterator
+ | "name" when in_meta -> check_arity_context_linetype s; TName
+ | "position" when in_meta -> check_arity_context_linetype s; TPosition
+ | "any" when in_meta -> check_arity_context_linetype s; TPosAny
+ | "pure" when in_meta && in_iso ->
+ check_arity_context_linetype s; TPure
+ | "context" when in_meta && in_iso ->
+ check_arity_context_linetype s; TContext
+ | "error" when in_meta -> check_arity_context_linetype s; TError
+ | "words" when in_meta -> check_context_linetype s; TWords
+
+ | "using" when in_rule_name || in_prolog -> check_context_linetype s; TUsing
+ | "disable" when in_rule_name -> check_context_linetype s; TDisable
+ | "extends" when in_rule_name -> check_context_linetype s; TExtends
+ | "depends" when in_rule_name -> check_context_linetype s; TDepends
+ | "on" when in_rule_name -> check_context_linetype s; TOn
+ | "ever" when in_rule_name -> check_context_linetype s; TEver
+ | "never" when in_rule_name -> check_context_linetype s; TNever
+ | "exists" when in_rule_name -> check_context_linetype s; TExists
+ | "forall" when in_rule_name -> check_context_linetype s; TForall
+ | "reverse" when in_rule_name -> check_context_linetype s; TReverse
+
+ | "char" -> Tchar linetype
+ | "short" -> Tshort linetype
+ | "int" -> Tint linetype
+ | "double" -> Tdouble linetype
+ | "float" -> Tfloat linetype
+ | "long" -> Tlong linetype
+ | "void" -> Tvoid linetype
+ | "struct" -> Tstruct linetype
+ | "union" -> Tunion linetype
+ | "unsigned" -> Tunsigned linetype
+ | "signed" -> Tsigned linetype
+
+ | "auto" -> Tauto linetype
+ | "register" -> Tregister linetype
+ | "extern" -> Textern linetype
+ | "static" -> Tstatic linetype
+ | "inline" -> Tinline linetype
+ | "typedef" -> Ttypedef linetype
+
+ | "const" -> Tconst linetype
+ | "volatile" -> Tvolatile linetype
+
+ | "if" -> TIf linetype
+ | "else" -> TElse linetype
+ | "while" -> TWhile linetype
+ | "do" -> TDo linetype
+ | "for" -> TFor linetype
+ | "switch" -> TSwitch linetype
+ | "case" -> TCase linetype
+ | "default" -> TDefault linetype
+ | "return" -> TReturn linetype
+ | "break" -> TBreak linetype
+ | "continue" -> TContinue linetype
+ | "goto" -> TGoto linetype
+
+ | "sizeof" -> TSizeof linetype
+
+ | "Expression" -> TIsoExpression
+ | "ArgExpression" -> TIsoArgExpression
+ | "TestExpression" -> TIsoTestExpression
+ | "Statement" -> TIsoStatement
+ | "Declaration" -> TIsoDeclaration
+ | "Type" -> TIsoType
+ | "TopLevel" -> TIsoTopLevel
+
+ | s -> check_var s linetype
+
+let mkassign op lexbuf =
+ TAssign (Ast.OpAssign op, (get_current_line_type lexbuf))
+
+let init _ =
+ line := 1;
+ logical_line := 0;
+ prev_plus := false;
+ line_start := 0;
+ current_line_started := false;
+ col_zero := true;
+ pm := UNKNOWN;
+ Data.in_rule_name := false;
+ Data.in_meta := false;
+ Data.in_prolog := false;
+ Data.inheritable_positions := [];
+ Hashtbl.clear all_metavariables;
+ Hashtbl.clear Data.all_metadecls;
+ Hashtbl.clear metavariables;
+ Hashtbl.clear type_names;
+ Hashtbl.clear rule_names;
+ let get_name (_,x) = x in
+ Data.add_id_meta :=
+ (fun name constraints pure ->
+ let fn clt = TMetaId(name,constraints,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_type_meta :=
+ (fun name pure ->
+ let fn clt = TMetaType(name,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_param_meta :=
+ (function name -> function pure ->
+ let fn clt = TMetaParam(name,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_paramlist_meta :=
+ (function name -> function lenname -> function pure ->
+ let fn clt = TMetaParamList(name,lenname,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_const_meta :=
+ (fun tyopt name constraints pure ->
+ let fn clt = TMetaConst(name,constraints,pure,tyopt,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_err_meta :=
+ (fun name constraints pure ->
+ let fn clt = TMetaErr(name,constraints,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_exp_meta :=
+ (fun tyopt name constraints pure ->
+ let fn clt = TMetaExp(name,constraints,pure,tyopt,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_idexp_meta :=
+ (fun tyopt name constraints pure ->
+ let fn clt = TMetaIdExp(name,constraints,pure,tyopt,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_local_idexp_meta :=
+ (fun tyopt name constraints pure ->
+ let fn clt = TMetaLocalIdExp(name,constraints,pure,tyopt,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_explist_meta :=
+ (function name -> function lenname -> function pure ->
+ let fn clt = TMetaExpList(name,lenname,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_stm_meta :=
+ (function name -> function pure ->
+ let fn clt = TMetaStm(name,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_stmlist_meta :=
+ (function name -> function pure ->
+ let fn clt = TMetaStmList(name,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_func_meta :=
+ (fun name constraints pure ->
+ let fn clt = TMetaFunc(name,constraints,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_local_func_meta :=
+ (fun name constraints pure ->
+ let fn clt = TMetaLocalFunc(name,constraints,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_iterator_meta :=
+ (fun name constraints pure ->
+ let fn clt = TMetaIterator(name,constraints,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_declarer_meta :=
+ (fun name constraints pure ->
+ let fn clt = TMetaDeclarer(name,constraints,pure,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_pos_meta :=
+ (fun name constraints any ->
+ let fn ((d,ln,_,_,_,_,_,_) as clt) =
+ (if d = Data.PLUS
+ then
+ failwith
+ (Printf.sprintf "%d: positions only allowed in minus code" ln));
+ TMetaPos(name,constraints,any,clt) in
+ Hashtbl.replace metavariables (get_name name) fn);
+ Data.add_type_name :=
+ (function name ->
+ let fn clt = TTypeId(name,clt) in
+ Hashtbl.replace type_names name fn);
+ Data.add_declarer_name :=
+ (function name ->
+ let fn clt = TDeclarerId(name,clt) in
+ Hashtbl.replace declarer_names name fn);
+ Data.add_iterator_name :=
+ (function name ->
+ let fn clt = TIteratorId(name,clt) in
+ Hashtbl.replace iterator_names name fn);
+ Data.init_rule := (function _ -> Hashtbl.clear metavariables);
+ Data.install_bindings :=
+ (function parent ->
+ List.iter (function (name,fn) -> Hashtbl.add metavariables name fn)
+ (Hashtbl.find all_metavariables parent))
+
+let drop_spaces s =
+ let len = String.length s in
+ let rec loop n =
+ if n = len
+ then n
+ else
+ if List.mem (String.get s n) [' ';'\t']
+ then loop (n+1)
+ else n in
+ let start = loop 0 in
+ String.sub s start (len - start)
+}
+
+(* ---------------------------------------------------------------------- *)
+(* tokens *)
+
+let letter = ['A'-'Z' 'a'-'z' '_']
+let digit = ['0'-'9']
+
+let dec = ['0'-'9']
+let oct = ['0'-'7']
+let hex = ['0'-'9' 'a'-'f' 'A'-'F']
+
+let decimal = ('0' | (['1'-'9'] dec*))
+let octal = ['0'] oct+
+let hexa = ("0x" |"0X") hex+
+
+let pent = dec+
+let pfract = dec+
+let sign = ['-' '+']
+let exp = ['e''E'] sign? dec+
+let real = pent exp | ((pent? '.' pfract | pent '.' pfract? ) exp?)
+
+
+rule token = parse
+ | [' ' '\t' ]+ { start_line false; token lexbuf }
+ | ['\n' '\r' '\011' '\012'] { reset_line lexbuf; token lexbuf }
+
+ | "//" [^ '\n']* { start_line false; token lexbuf }
+
+ | "@@" { start_line true; TArobArob }
+ | "@" { pass_zero();
+ if !Data.in_rule_name or not !current_line_started
+ then (start_line true; TArob)
+ else (check_minus_context_linetype "@"; TPArob) }
+
+ | "WHEN" | "when"
+ { start_line true; check_minus_context_linetype (tok lexbuf);
+ TWhen (get_current_line_type lexbuf) }
+
+ | "..."
+ { start_line true; check_minus_context_linetype (tok lexbuf);
+ TEllipsis (get_current_line_type lexbuf) }
+(*
+ | "ooo"
+ { start_line true; check_minus_context_linetype (tok lexbuf);
+ TCircles (get_current_line_type lexbuf) }
+
+ | "***"
+ { start_line true; check_minus_context_linetype (tok lexbuf);
+ TStars (get_current_line_type lexbuf) }
+*)
+ | "<..." { start_line true; check_context_linetype (tok lexbuf);
+ TOEllipsis (get_current_line_type lexbuf) }
+ | "...>" { start_line true; check_context_linetype (tok lexbuf);
+ TCEllipsis (get_current_line_type lexbuf) }
+ | "<+..." { start_line true; check_context_linetype (tok lexbuf);
+ TPOEllipsis (get_current_line_type lexbuf) }
+ | "...+>" { start_line true; check_context_linetype (tok lexbuf);
+ TPCEllipsis (get_current_line_type lexbuf) }
+(*
+ | "<ooo" { start_line true; check_context_linetype (tok lexbuf);
+ TOCircles (get_current_line_type lexbuf) }
+ | "ooo>" { start_line true; check_context_linetype (tok lexbuf);
+ TCCircles (get_current_line_type lexbuf) }
+
+ | "<***" { start_line true; check_context_linetype (tok lexbuf);
+ TOStars (get_current_line_type lexbuf) }
+ | "***>" { start_line true; check_context_linetype (tok lexbuf);
+ TCStars (get_current_line_type lexbuf) }
+*)
+ | "-" { pass_zero();
+ if !current_line_started
+ then (start_line true; TMinus (get_current_line_type lexbuf))
+ else (patch_or_match PATCH;
+ add_current_line_type D.MINUS; token lexbuf) }
+ | "+" { pass_zero();
+ if !current_line_started
+ then (start_line true; TPlus (get_current_line_type lexbuf))
+ else if !Data.in_meta
+ then TPlus0
+ else (patch_or_match PATCH;
+ add_current_line_type D.PLUS; token lexbuf) }
+ | "?" { pass_zero();
+ if !current_line_started
+ then (start_line true; TWhy (get_current_line_type lexbuf))
+ else if !Data.in_meta
+ then TWhy0
+ else (add_current_line_type D.OPT; token lexbuf) }
+ | "!" { pass_zero();
+ if !current_line_started
+ then (start_line true; TBang (get_current_line_type lexbuf))
+ else if !Data.in_meta
+ then TBang0
+ else (add_current_line_type D.UNIQUE; token lexbuf) }
+ | "(" { if not !col_zero
+ then (start_line true; TOPar (get_current_line_type lexbuf))
+ else
+ (start_line true; check_context_linetype (tok lexbuf);
+ TOPar0 (get_current_line_type lexbuf))}
+ | "\\(" { start_line true; TOPar0 (get_current_line_type lexbuf) }
+ | "|" { if not (!col_zero)
+ then (start_line true; TOr(get_current_line_type lexbuf))
+ else (start_line true;
+ check_context_linetype (tok lexbuf);
+ TMid0 (get_current_line_type lexbuf))}
+ | "\\|" { start_line true; TMid0 (get_current_line_type lexbuf) }
+ | ")" { if not !col_zero
+ then (start_line true; TCPar (get_current_line_type lexbuf))
+ else
+ (start_line true; check_context_linetype (tok lexbuf);
+ TCPar0 (get_current_line_type lexbuf))}
+ | "\\)" { start_line true; TCPar0 (get_current_line_type lexbuf) }
+
+ | '[' { start_line true; TOCro (get_current_line_type lexbuf) }
+ | ']' { start_line true; TCCro (get_current_line_type lexbuf) }
+ | '{' { start_line true; TOBrace (get_current_line_type lexbuf) }
+ | '}' { start_line true; TCBrace (get_current_line_type lexbuf) }
+
+ | "->" { start_line true; TPtrOp (get_current_line_type lexbuf) }
+ | '.' { start_line true; TDot (get_current_line_type lexbuf) }
+ | ',' { start_line true; TComma (get_current_line_type lexbuf) }
+ | ";" { start_line true;
+ if !Data.in_meta
+ then TMPtVirg (* works better with tokens_all *)
+ else TPtVirg (get_current_line_type lexbuf) }
+
+
+ | '*' { pass_zero();
+ if !current_line_started
+ then
+ (start_line true; TMul (get_current_line_type lexbuf))
+ else
+ (patch_or_match MATCH;
+ add_current_line_type D.MINUS; token lexbuf) }
+ | '/' { start_line true;
+ TDmOp (Ast.Div,get_current_line_type lexbuf) }
+ | '%' { start_line true;
+ TDmOp (Ast.Mod,get_current_line_type lexbuf) }
+ | '~' { start_line true; TTilde (get_current_line_type lexbuf) }
+
+ | "++" { start_line true; TInc (get_current_line_type lexbuf) }
+ | "--" { start_line true; TDec (get_current_line_type lexbuf) }
+
+ | "=" { start_line true; TEq (get_current_line_type lexbuf) }
+
+ | "-=" { start_line true; mkassign Ast.Minus lexbuf }
+ | "+=" { start_line true; mkassign Ast.Plus lexbuf }
+
+ | "*=" { start_line true; mkassign Ast.Mul lexbuf }
+ | "/=" { start_line true; mkassign Ast.Div lexbuf }
+ | "%=" { start_line true; mkassign Ast.Mod lexbuf }
+
+ | "&=" { start_line true; mkassign Ast.And lexbuf }
+ | "|=" { start_line true; mkassign Ast.Or lexbuf }
+ | "^=" { start_line true; mkassign Ast.Xor lexbuf }
+
+ | "<<=" { start_line true; mkassign Ast.DecLeft lexbuf }
+ | ">>=" { start_line true; mkassign Ast.DecRight lexbuf }
+
+ | ":" { start_line true; TDotDot (get_current_line_type lexbuf) }
+
+ | "==" { start_line true; TEqEq (get_current_line_type lexbuf) }
+ | "!=" { start_line true; TNotEq (get_current_line_type lexbuf) }
+ | ">=" { start_line true;
+ TLogOp(Ast.SupEq,get_current_line_type lexbuf) }
+ | "<=" { start_line true;
+ TLogOp(Ast.InfEq,get_current_line_type lexbuf) }
+ | "<" { start_line true;
+ TLogOp(Ast.Inf,get_current_line_type lexbuf) }
+ | ">" { start_line true;
+ TLogOp(Ast.Sup,get_current_line_type lexbuf) }
+
+ | "&&" { start_line true; TAndLog (get_current_line_type lexbuf) }
+ | "||" { start_line true; TOrLog (get_current_line_type lexbuf) }
+
+ | ">>" { start_line true;
+ TShOp(Ast.DecRight,get_current_line_type lexbuf) }
+ | "<<" { start_line true;
+ TShOp(Ast.DecLeft,get_current_line_type lexbuf) }
+
+ | "&" { start_line true; TAnd (get_current_line_type lexbuf) }
+ | "^" { start_line true; TXor(get_current_line_type lexbuf) }
+
+ | ( ("#" [' ' '\t']* "define" [' ' '\t']+))
+ ( (letter (letter |digit)*) as ident)
+ { start_line true;
+ let (arity,line,lline,offset,col,strbef,straft,pos) as lt =
+ get_current_line_type lexbuf in
+ let off = String.length "#define " in
+ (* -1 in the code below because the ident is not at the line start *)
+ TDefine
+ (lt,
+ check_var ident
+ (arity,line,lline,offset+off,(-1),[],[],Ast0.NoMetaPos)) }
+ | ( ("#" [' ' '\t']* "define" [' ' '\t']+))
+ ( (letter (letter | digit)*) as ident)
+ '('
+ { start_line true;
+ let (arity,line,lline,offset,col,strbef,straft,pos) as lt =
+ get_current_line_type lexbuf in
+ let off = String.length "#define " in
+ TDefineParam
+ (lt,
+ check_var ident
+ (* why pos here but not above? *)
+ (arity,line,lline,offset+off,(-1),strbef,straft,pos),
+ offset + off + (String.length ident)) }
+ | "#" [' ' '\t']* "include" [' ' '\t']* '"' [^ '"']+ '"'
+ { TIncludeL
+ (let str = tok lexbuf in
+ let start = String.index str '"' in
+ let finish = String.rindex str '"' in
+ start_line true;
+ (process_include start finish str,get_current_line_type lexbuf)) }
+ | "#" [' ' '\t']* "include" [' ' '\t']* '<' [^ '>']+ '>'
+ { TIncludeNL
+ (let str = tok lexbuf in
+ let start = String.index str '<' in
+ let finish = String.rindex str '>' in
+ start_line true;
+ (process_include start finish str,get_current_line_type lexbuf)) }
+ | "#" [' ' '\t']* "if" [^'\n']*
+ | "#" [' ' '\t']* "ifdef" [^'\n']*
+ | "#" [' ' '\t']* "ifndef" [^'\n']*
+ | "#" [' ' '\t']* "else" [^'\n']*
+ | "#" [' ' '\t']* "elif" [^'\n']*
+ | "#" [' ' '\t']* "endif" [^'\n']*
+ | "#" [' ' '\t']* "error" [^'\n']*
+ { start_line true; check_plus_linetype (tok lexbuf);
+ TPragma (tok lexbuf) }
+ | "---" [^'\n']*
+ { (if !current_line_started
+ then lexerr "--- must be at the beginning of the line" "");
+ start_line true;
+ TMinusFile
+ (let str = tok lexbuf in
+ (drop_spaces(String.sub str 3 (String.length str - 3)),
+ (get_current_line_type lexbuf))) }
+ | "+++" [^'\n']*
+ { (if !current_line_started
+ then lexerr "+++ must be at the beginning of the line" "");
+ start_line true;
+ TPlusFile
+ (let str = tok lexbuf in
+ (drop_spaces(String.sub str 3 (String.length str - 3)),
+ (get_current_line_type lexbuf))) }
+
+ | letter (letter | digit)*
+ { start_line true; id_tokens lexbuf }
+
+ | "'" { start_line true;
+ TChar(char lexbuf,get_current_line_type lexbuf) }
+ | '"' { start_line true;
+ TString(string lexbuf,(get_current_line_type lexbuf)) }
+ | (real as x) { start_line true;
+ TFloat(x,(get_current_line_type lexbuf)) }
+ | ((( decimal | hexa | octal)
+ ( ['u' 'U']
+ | ['l' 'L']
+ | (['l' 'L'] ['u' 'U'])
+ | (['u' 'U'] ['l' 'L'])
+ | (['u' 'U'] ['l' 'L'] ['l' 'L'])
+ | (['l' 'L'] ['l' 'L'])
+ )?
+ ) as x) { start_line true; TInt(x,(get_current_line_type lexbuf)) }
+
+ | "<=>" { TIso }
+ | "=>" { TRightIso }
+
+ | eof { EOF }
+
+ | _ { lexerr "unrecognised symbol, in token rule: " (tok lexbuf) }
+
+
+and char = parse
+ | (_ as x) "'" { String.make 1 x }
+ | (("\\" (oct | oct oct | oct oct oct)) as x "'") { x }
+ | (("\\x" (hex | hex hex)) as x "'") { x }
+ | (("\\" (_ as v)) as x "'")
+ { (match v with
+ | 'n' -> () | 't' -> () | 'v' -> () | 'b' -> ()
+ | 'r' -> () | 'f' -> () | 'a' -> ()
+ | '\\' -> () | '?' -> () | '\'' -> () | '"' -> ()
+ | 'e' -> ()
+ | _ -> lexerr "unrecognised symbol: " (tok lexbuf)
+ );
+ x
+ }
+ | _ { lexerr "unrecognised symbol: " (tok lexbuf) }
+
+and string = parse
+ | '"' { "" }
+ | (_ as x) { Common.string_of_char x ^ string lexbuf }
+ | ("\\" (oct | oct oct | oct oct oct)) as x { x ^ string lexbuf }
+ | ("\\x" (hex | hex hex)) as x { x ^ string lexbuf }
+ | ("\\" (_ as v)) as x
+ {
+ (match v with
+ | 'n' -> () | 't' -> () | 'v' -> () | 'b' -> () | 'r' -> ()
+ | 'f' -> () | 'a' -> ()
+ | '\\' -> () | '?' -> () | '\'' -> () | '"' -> ()
+ | 'e' -> ()
+ | '\n' -> ()
+ | _ -> lexerr "unrecognised symbol:" (tok lexbuf)
+ );
+ x ^ string lexbuf
+ }
+ | _ { lexerr "unrecognised symbol: " (tok lexbuf) }
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* exports everything, used only by parser_cocci_menhir.mly *)
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+
+(* types for metavariable tokens *)
+type info = Ast.meta_name * Ast0.pure * Data.clt
+type idinfo = Ast.meta_name * Data.iconstraints * Ast0.pure * Data.clt
+type expinfo = Ast.meta_name * Data.econstraints * Ast0.pure * Data.clt
+type tyinfo = Ast.meta_name * Ast0.typeC list * Ast0.pure * Data.clt
+type list_info = Ast.meta_name * Ast.meta_name option * Ast0.pure * Data.clt
+type typed_info =
+ Ast.meta_name * Data.econstraints * Ast0.pure *
+ Type_cocci.typeC list option * Data.clt
+type pos_info = Ast.meta_name * Data.pconstraints * Ast.meta_collect * Data.clt
+
+
+let get_option fn = function
+ None -> None
+ | Some x -> Some (fn x)
+
+let make_info line logical_line offset col strbef straft =
+ { Ast0.line_start = line; Ast0.line_end = line;
+ Ast0.logical_start = logical_line; Ast0.logical_end = logical_line;
+ Ast0.attachable_start = true; Ast0.attachable_end = true;
+ Ast0.mcode_start = []; Ast0.mcode_end = [];
+ Ast0.column = col; Ast0.offset = offset;
+ Ast0.strings_before = strbef; Ast0.strings_after = straft; }
+
+let clt2info (_,line,logical_line,offset,col,strbef,straft,pos) =
+ make_info line logical_line offset col strbef straft
+
+let drop_bef (arity,line,lline,offset,col,strbef,straft,pos) =
+ (arity,line,lline,offset,col,[],straft,pos)
+
+let drop_aft (arity,line,lline,offset,col,strbef,straft,pos) =
+ (arity,line,lline,offset,col,strbef,[],pos)
+
+let clt2mcode str = function
+ (Data.MINUS,line,lline,offset,col,strbef,straft,pos) ->
+ (str,Ast0.NONE,make_info line lline offset col strbef straft,
+ Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos)
+ | (Data.OPTMINUS,line,lline,offset,col,strbef,straft,pos) ->
+ (str,Ast0.OPT,make_info line lline offset col strbef straft,
+ Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos)
+ | (Data.UNIQUEMINUS,line,lline,offset,col,strbef,straft,pos) ->
+ (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
+ Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos)
+ | (Data.PLUS,line,lline,offset,col,strbef,straft,pos) ->
+ (str,Ast0.NONE,make_info line lline offset col strbef straft,Ast0.PLUS,
+ ref pos)
+ | (Data.CONTEXT,line,lline,offset,col,strbef,straft,pos) ->
+ (str,Ast0.NONE,make_info line lline offset col strbef straft,
+ Ast0.CONTEXT(ref(Ast.NOTHING,
+ Ast0.default_token_info,Ast0.default_token_info)),
+ ref pos)
+ | (Data.OPT,line,lline,offset,col,strbef,straft,pos) ->
+ (str,Ast0.OPT,make_info line lline offset col strbef straft,
+ Ast0.CONTEXT(ref(Ast.NOTHING,
+ Ast0.default_token_info,Ast0.default_token_info)),
+ ref pos)
+ | (Data.UNIQUE,line,lline,offset,col,strbef,straft,pos) ->
+ (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
+ Ast0.CONTEXT(ref(Ast.NOTHING,
+ Ast0.default_token_info,Ast0.default_token_info)),
+ ref pos)
+
+let id2name (name, clt) = name
+let id2clt (name, clt) = clt
+let id2mcode (name, clt) = clt2mcode name clt
+
+let mkdots str (dot,whencode) =
+ match str with
+ "..." -> Ast0.wrap(Ast0.Dots(clt2mcode str dot, whencode))
+ | "ooo" -> Ast0.wrap(Ast0.Circles(clt2mcode str dot, whencode))
+ | "***" -> Ast0.wrap(Ast0.Stars(clt2mcode str dot, whencode))
+ | _ -> failwith "cannot happen"
+
+let mkedots str (dot,whencode) =
+ match str with
+ "..." -> Ast0.wrap(Ast0.Edots(clt2mcode str dot, whencode))
+ | "ooo" -> Ast0.wrap(Ast0.Ecircles(clt2mcode str dot, whencode))
+ | "***" -> Ast0.wrap(Ast0.Estars(clt2mcode str dot, whencode))
+ | _ -> failwith "cannot happen"
+
+let mkdpdots str dot =
+ match str with
+ "..." -> Ast0.wrap(Ast0.DPdots(clt2mcode str dot))
+ | "ooo" -> Ast0.wrap(Ast0.DPcircles(clt2mcode str dot))
+ | _ -> failwith "cannot happen"
+
+let mkidots str (dot,whencode) =
+ match str with
+ "..." -> Ast0.wrap(Ast0.Idots(clt2mcode str dot, whencode))
+ | _ -> failwith "cannot happen"
+
+let mkddots str (dot,whencode) =
+ match (str,whencode) with
+ ("...",None) -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, None))
+ | ("...",Some [w]) -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, Some w))
+ | _ -> failwith "cannot happen"
+
+let mkpdots str dot =
+ match str with
+ "..." -> Ast0.wrap(Ast0.Pdots(clt2mcode str dot))
+ | "ooo" -> Ast0.wrap(Ast0.Pcircles(clt2mcode str dot))
+ | _ -> failwith "cannot happen"
+
+let arith_op ast_op left op right =
+ Ast0.wrap
+ (Ast0.Binary(left, clt2mcode (Ast.Arith ast_op) op, right))
+
+let logic_op ast_op left op right =
+ Ast0.wrap
+ (Ast0.Binary(left, clt2mcode (Ast.Logical ast_op) op, right))
+
+let make_cv cv ty =
+ match cv with None -> ty | Some x -> Ast0.wrap (Ast0.ConstVol(x,ty))
+
+let top_dots l =
+ let circle x =
+ match Ast0.unwrap x with Ast0.Circles(_) -> true | _ -> false in
+ let star x =
+ match Ast0.unwrap x with Ast0.Stars(_) -> true | _ -> false in
+ if List.exists circle l
+ then Ast0.wrap(Ast0.CIRCLES(l))
+ else
+ if List.exists star l
+ then Ast0.wrap(Ast0.STARS(l))
+ else Ast0.wrap(Ast0.DOTS(l))
+
+(* here the offset is that of the first in the sequence of *s, not that of
+each * individually *)
+let pointerify ty m =
+ List.fold_left
+ (function inner ->
+ function cur ->
+ Ast0.wrap(Ast0.Pointer(inner,clt2mcode "*" cur)))
+ ty m
+
+let ty_pointerify ty m =
+ List.fold_left
+ (function inner -> function cur -> Type_cocci.Pointer(inner))
+ ty m
+
+(* Left is <=>, Right is =>. Collect <=>s. *)
+(* The parser should have done this, with precedences. But whatever... *)
+let iso_adjust fn first rest =
+ let rec loop = function
+ [] -> [[]]
+ | (Common.Left x)::rest ->
+ (match loop rest with
+ front::after -> (fn x::front)::after
+ | _ -> failwith "not possible")
+ | (Common.Right x)::rest ->
+ (match loop rest with
+ front::after -> []::(fn x::front)::after
+ | _ -> failwith "not possible") in
+ match loop rest with
+ front::after -> (fn first::front)::after
+ | _ -> failwith "not possible"
+
+let check_meta tok =
+ let lookup rule name =
+ try
+ let info = Hashtbl.find Data.all_metadecls rule in
+ List.find (function mv -> Ast.get_meta_name mv = (rule,name)) info
+ with
+ Not_found ->
+ raise
+ (Semantic_cocci.Semantic
+ ("bad rule "^rule^" or bad variable "^name)) in
+ match tok with
+ Ast.MetaIdDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaIdDecl(_,_) | Ast.MetaFreshIdDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaFreshIdDecl(Ast.NONE,(rule,name)) ->
+ raise
+ (Semantic_cocci.Semantic
+ "can't inherit the freshness of an identifier")
+ | Ast.MetaListlenDecl((rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaListlenDecl(_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaTypeDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaTypeDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaParamDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaParamDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaParamListDecl(Ast.NONE,(rule,name),len_name) ->
+ (match lookup rule name with
+ Ast.MetaParamListDecl(_,_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaErrDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaErrDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaExpDecl(Ast.NONE,(rule,name),ty) ->
+ (match lookup rule name with
+ Ast.MetaExpDecl(_,_,ty1) when ty = ty1 -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaIdExpDecl(Ast.NONE,(rule,name),ty) ->
+ (match lookup rule name with
+ Ast.MetaIdExpDecl(_,_,ty1) when ty = ty1 -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaLocalIdExpDecl(Ast.NONE,(rule,name),ty) ->
+ (match lookup rule name with
+ Ast.MetaLocalIdExpDecl(_,_,ty1) when ty = ty1 -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaExpListDecl(Ast.NONE,(rule,name),len_name) ->
+ (match lookup rule name with
+ Ast.MetaExpListDecl(_,_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaStmDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaStmDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaStmListDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaStmListDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaFuncDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaFuncDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaLocalFuncDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaLocalFuncDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaConstDecl(Ast.NONE,(rule,name),ty) ->
+ (match lookup rule name with
+ Ast.MetaConstDecl(_,_,ty1) when ty = ty1 -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaPosDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaPosDecl(_,_) ->
+ if not (List.mem rule !Data.inheritable_positions)
+ then
+ raise
+ (Semantic_cocci.Semantic
+ ("position cannot be inherited over modifications: "^name))
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic ("arity not allowed on imported declaration"))
+
+let create_metadec ar ispure kindfn ids current_rule =
+ List.concat
+ (List.map
+ (function (rule,nm) ->
+ let (rule,checker) =
+ match rule with
+ None -> ((current_rule,nm),function x -> [Common.Left x])
+ | Some rule ->
+ ((rule,nm),
+ function x -> check_meta x; [Common.Right x]) in
+ kindfn ar rule ispure checker)
+ ids)
+
+let create_metadec_ne ar ispure kindfn ids current_rule =
+ List.concat
+ (List.map
+ (function ((rule,nm),constraints) ->
+ let (rule,checker) =
+ match rule with
+ None -> ((current_rule,nm),function x -> [Common.Left x])
+ | Some rule ->
+ ((rule,nm),
+ function x -> check_meta x; [Common.Right x]) in
+ kindfn ar rule ispure checker constraints)
+ ids)
+
+let create_metadec_ty ar ispure kindfn ids current_rule =
+ List.concat
+ (List.map
+ (function ((rule,nm),constraints) ->
+ let (rule,checker) =
+ match rule with
+ None -> ((current_rule,nm),function x -> [Common.Left x])
+ | Some rule ->
+ ((rule,nm),
+ function x -> check_meta x; [Common.Right x]) in
+ kindfn ar rule ispure checker constraints)
+ ids)
+
+let create_len_metadec ar ispure kindfn lenid ids current_rule =
+ let lendec =
+ create_metadec Ast.NONE Ast0.Impure
+ (fun _ name _ check_meta -> check_meta(Ast.MetaListlenDecl(name)))
+ [lenid] current_rule in
+ let lenname =
+ match lendec with
+ [Common.Left (Ast.MetaListlenDecl(x))] -> x
+ | [Common.Right (Ast.MetaListlenDecl(x))] -> x
+ | _ -> failwith "unexpected length declaration" in
+ lendec@(create_metadec ar ispure (kindfn lenname) ids current_rule)
+
+(* ---------------------------------------------------------------------- *)
+
+let str2inc s =
+ let elements = Str.split (Str.regexp "/") s in
+ List.map (function "..." -> Ast.IncDots | s -> Ast.IncPath s) elements
+
+(* ---------------------------------------------------------------------- *)
+(* statements *)
+
+let meta_stm name =
+ let (nm,pure,clt) = name in
+ Ast0.wrap(Ast0.MetaStmt(clt2mcode nm clt,pure))
+
+let exp_stm exp pv =
+ Ast0.wrap(Ast0.ExprStatement (exp, clt2mcode ";" pv))
+
+let ifthen iff lp tst rp thn =
+ Ast0.wrap(Ast0.IfThen(clt2mcode "if" iff,
+ clt2mcode "(" lp,tst,clt2mcode ")" rp,thn,
+ (Ast0.default_info(),Ast0.context_befaft())))
+
+let ifthenelse iff lp tst rp thn e els =
+ Ast0.wrap(Ast0.IfThenElse(clt2mcode "if" iff,
+ clt2mcode "(" lp,tst,clt2mcode ")" rp,thn,
+ clt2mcode "else" e,els,
+ (Ast0.default_info(),Ast0.context_befaft())))
+
+let forloop fr lp e1 sc1 e2 sc2 e3 rp s =
+ Ast0.wrap(Ast0.For(clt2mcode "for" fr,clt2mcode "(" lp,e1,
+ clt2mcode ";" sc1,e2,
+ clt2mcode ";" sc2,e3,clt2mcode ")" rp,s,
+ (Ast0.default_info(),Ast0.context_befaft())))
+
+let whileloop w lp e rp s =
+ Ast0.wrap(Ast0.While(clt2mcode "while" w,clt2mcode "(" lp,
+ e,clt2mcode ")" rp,s,
+ (Ast0.default_info(),Ast0.context_befaft())))
+
+let doloop d s w lp e rp pv =
+ Ast0.wrap(Ast0.Do(clt2mcode "do" d,s,clt2mcode "while" w,
+ clt2mcode "(" lp,e,clt2mcode ")" rp,
+ clt2mcode ";" pv))
+
+let iterator i lp e rp s =
+ Ast0.wrap(Ast0.Iterator(i,clt2mcode "(" lp,e,clt2mcode ")" rp,s,
+ (Ast0.default_info(),Ast0.context_befaft())))
+
+let switch s lp e rp lb c rb =
+ Ast0.wrap(Ast0.Switch(clt2mcode "switch" s,clt2mcode "(" lp,e,
+ clt2mcode ")" rp,clt2mcode "{" lb,
+ Ast0.wrap(Ast0.DOTS(c)),clt2mcode "}" rb))
+
+let ret_exp r e pv =
+ Ast0.wrap(Ast0.ReturnExpr(clt2mcode "return" r,e,clt2mcode ";" pv))
+
+let ret r pv =
+ Ast0.wrap(Ast0.Return(clt2mcode "return" r,clt2mcode ";" pv))
+
+let break b pv =
+ Ast0.wrap(Ast0.Break(clt2mcode "break" b,clt2mcode ";" pv))
+
+let cont c pv =
+ Ast0.wrap(Ast0.Continue(clt2mcode "continue" c,clt2mcode ";" pv))
+
+let label i dd =
+ Ast0.wrap(Ast0.Label(i,clt2mcode ":" dd))
+
+let goto g i pv =
+ Ast0.wrap(Ast0.Goto(clt2mcode "goto" g,i,clt2mcode ";" pv))
+
+let seq lb s rb =
+ Ast0.wrap(Ast0.Seq(clt2mcode "{" lb,s,clt2mcode "}" rb))
+
+(* ---------------------------------------------------------------------- *)
+
+let make_iso_rule_name_result n =
+ (try let _ = Hashtbl.find Data.all_metadecls n in
+ raise (Semantic_cocci.Semantic ("repeated rule name"))
+ with Not_found -> ());
+ Ast.CocciRulename (Some n,Ast.NoDep,[],[],Ast.Undetermined,false (*discarded*))
+
+let make_cocci_rule_name_result nm d i a e ee =
+ match nm with
+ Some nm ->
+ let n = id2name nm in
+ (try let _ = Hashtbl.find Data.all_metadecls n in
+ raise (Semantic_cocci.Semantic ("repeated rule name"))
+ with Not_found -> ());
+ Ast.CocciRulename (Some n,d,i,a,e,ee)
+ | None -> Ast.CocciRulename (None,d,i,a,e,ee)
+
+let make_script_rule_name_result scr lang deps =
+ let s = id2name scr in
+ let l = id2name lang in
+ if s <> "script" then
+ raise (Semantic_cocci.Semantic ("malformed script rule"));
+ Ast.ScriptRulename (l,deps)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* splits the entire file into minus and plus fragments, and parses each
+separately (thus duplicating work for the parsing of the context elements) *)
+
+module D = Data
+module PC = Parser_cocci_menhir
+module V0 = Visitor_ast0
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+let pr = Printf.sprintf
+(*let pr2 s = prerr_string s; prerr_string "\n"; flush stderr*)
+let pr2 s = Printf.printf "%s\n" s
+
+(* for isomorphisms. all should be at the front!!! *)
+let reserved_names =
+ ["all";"optional_storage";"optional_qualifier";"value_format";"comm_assoc"]
+
+(* ----------------------------------------------------------------------- *)
+(* Debugging... *)
+
+let line_type (d,_,_,_,_,_,_,_) = d
+
+let line_type2c tok =
+ match line_type tok with
+ D.MINUS | D.OPTMINUS | D.UNIQUEMINUS -> ":-"
+ | D.PLUS -> ":+"
+ | D.CONTEXT | D.UNIQUE | D.OPT -> ""
+
+let token2c (tok,_) =
+ match tok with
+ PC.TIdentifier -> "identifier"
+ | PC.TType -> "type"
+ | PC.TParameter -> "parameter"
+ | PC.TConstant -> "constant"
+ | PC.TExpression -> "expression"
+ | PC.TIdExpression -> "idexpression"
+ | PC.TStatement -> "statement"
+ | PC.TPosition -> "position"
+ | PC.TPosAny -> "any"
+ | PC.TFunction -> "function"
+ | PC.TLocal -> "local"
+ | PC.Tlist -> "list"
+ | PC.TFresh -> "fresh"
+ | PC.TPure -> "pure"
+ | PC.TContext -> "context"
+ | PC.TTypedef -> "typedef"
+ | PC.TDeclarer -> "declarer"
+ | PC.TIterator -> "iterator"
+ | PC.TName -> "name"
+ | PC.TRuleName str -> "rule_name-"^str
+ | PC.TUsing -> "using"
+ | PC.TPathIsoFile str -> "path_iso_file-"^str
+ | PC.TDisable -> "disable"
+ | PC.TExtends -> "extends"
+ | PC.TDepends -> "depends"
+ | PC.TOn -> "on"
+ | PC.TEver -> "ever"
+ | PC.TNever -> "never"
+ | PC.TExists -> "exists"
+ | PC.TForall -> "forall"
+ | PC.TReverse -> "reverse"
+ | PC.TError -> "error"
+ | PC.TWords -> "words"
+
+ | PC.TNothing -> "nothing"
+
+ | PC.Tchar(clt) -> "char"^(line_type2c clt)
+ | PC.Tshort(clt) -> "short"^(line_type2c clt)
+ | PC.Tint(clt) -> "int"^(line_type2c clt)
+ | PC.Tdouble(clt) -> "double"^(line_type2c clt)
+ | PC.Tfloat(clt) -> "float"^(line_type2c clt)
+ | PC.Tlong(clt) -> "long"^(line_type2c clt)
+ | PC.Tvoid(clt) -> "void"^(line_type2c clt)
+ | PC.Tstruct(clt) -> "struct"^(line_type2c clt)
+ | PC.Tunion(clt) -> "union"^(line_type2c clt)
+ | PC.Tunsigned(clt) -> "unsigned"^(line_type2c clt)
+ | PC.Tsigned(clt) -> "signed"^(line_type2c clt)
+ | PC.Tstatic(clt) -> "static"^(line_type2c clt)
+ | PC.Tinline(clt) -> "inline"^(line_type2c clt)
+ | PC.Ttypedef(clt) -> "typedef"^(line_type2c clt)
+ | PC.Tattr(s,clt) -> s^(line_type2c clt)
+ | PC.Tauto(clt) -> "auto"^(line_type2c clt)
+ | PC.Tregister(clt) -> "register"^(line_type2c clt)
+ | PC.Textern(clt) -> "extern"^(line_type2c clt)
+ | PC.Tconst(clt) -> "const"^(line_type2c clt)
+ | PC.Tvolatile(clt) -> "volatile"^(line_type2c clt)
+
+ | PC.TPragma(s) -> s
+ | PC.TIncludeL(s,clt) -> (pr "#include \"%s\"" s)^(line_type2c clt)
+ | PC.TIncludeNL(s,clt) -> (pr "#include <%s>" s)^(line_type2c clt)
+ | PC.TDefine(clt,_) -> "#define"^(line_type2c clt)
+ | PC.TDefineParam(clt,_,_) -> "#define_param"^(line_type2c clt)
+ | PC.TMinusFile(s,clt) -> (pr "--- %s" s)^(line_type2c clt)
+ | PC.TPlusFile(s,clt) -> (pr "+++ %s" s)^(line_type2c clt)
+
+ | PC.TInc(clt) -> "++"^(line_type2c clt)
+ | PC.TDec(clt) -> "--"^(line_type2c clt)
+
+ | PC.TIf(clt) -> "if"^(line_type2c clt)
+ | PC.TElse(clt) -> "else"^(line_type2c clt)
+ | PC.TWhile(clt) -> "while"^(line_type2c clt)
+ | PC.TFor(clt) -> "for"^(line_type2c clt)
+ | PC.TDo(clt) -> "do"^(line_type2c clt)
+ | PC.TSwitch(clt) -> "switch"^(line_type2c clt)
+ | PC.TCase(clt) -> "case"^(line_type2c clt)
+ | PC.TDefault(clt) -> "default"^(line_type2c clt)
+ | PC.TReturn(clt) -> "return"^(line_type2c clt)
+ | PC.TBreak(clt) -> "break"^(line_type2c clt)
+ | PC.TContinue(clt) -> "continue"^(line_type2c clt)
+ | PC.TGoto(clt) -> "goto"^(line_type2c clt)
+ | PC.TIdent(s,clt) -> (pr "ident-%s" s)^(line_type2c clt)
+ | PC.TTypeId(s,clt) -> (pr "typename-%s" s)^(line_type2c clt)
+ | PC.TDeclarerId(s,clt) -> (pr "declarername-%s" s)^(line_type2c clt)
+ | PC.TIteratorId(s,clt) -> (pr "iteratorname-%s" s)^(line_type2c clt)
+ | PC.TMetaDeclarer(_,_,_,clt) -> "declmeta"^(line_type2c clt)
+ | PC.TMetaIterator(_,_,_,clt) -> "itermeta"^(line_type2c clt)
+
+ | PC.TSizeof(clt) -> "sizeof"^(line_type2c clt)
+
+ | PC.TString(x,clt) -> x^(line_type2c clt)
+ | PC.TChar(x,clt) -> x^(line_type2c clt)
+ | PC.TFloat(x,clt) -> x^(line_type2c clt)
+ | PC.TInt(x,clt) -> x^(line_type2c clt)
+
+ | PC.TOrLog(clt) -> "||"^(line_type2c clt)
+ | PC.TAndLog(clt) -> "&&"^(line_type2c clt)
+ | PC.TOr(clt) -> "|"^(line_type2c clt)
+ | PC.TXor(clt) -> "^"^(line_type2c clt)
+ | PC.TAnd (clt) -> "&"^(line_type2c clt)
+ | PC.TEqEq(clt) -> "=="^(line_type2c clt)
+ | PC.TNotEq(clt) -> "!="^(line_type2c clt)
+ | PC.TLogOp(op,clt) ->
+ (match op with
+ Ast.Inf -> "<"
+ | Ast.InfEq -> "<="
+ | Ast.Sup -> ">"
+ | Ast.SupEq -> ">="
+ | _ -> failwith "not possible")
+ ^(line_type2c clt)
+ | PC.TShOp(op,clt) ->
+ (match op with
+ Ast.DecLeft -> "<<"
+ | Ast.DecRight -> ">>"
+ | _ -> failwith "not possible")
+ ^(line_type2c clt)
+ | PC.TPlus(clt) -> "+"^(line_type2c clt)
+ | PC.TMinus(clt) -> "-"^(line_type2c clt)
+ | PC.TMul(clt) -> "*"^(line_type2c clt)
+ | PC.TDmOp(op,clt) ->
+ (match op with
+ Ast.Div -> "/"
+ | Ast.Mod -> "%"
+ | _ -> failwith "not possible")
+ ^(line_type2c clt)
+ | PC.TTilde (clt) -> "~"^(line_type2c clt)
+
+ | PC.TMetaParam(_,_,clt) -> "parammeta"^(line_type2c clt)
+ | PC.TMetaParamList(_,_,_,clt) -> "paramlistmeta"^(line_type2c clt)
+ | PC.TMetaConst(_,_,_,_,clt) -> "constmeta"^(line_type2c clt)
+ | PC.TMetaErr(_,_,_,clt) -> "errmeta"^(line_type2c clt)
+ | PC.TMetaExp(_,_,_,_,clt) -> "expmeta"^(line_type2c clt)
+ | PC.TMetaIdExp(_,_,_,_,clt) -> "idexpmeta"^(line_type2c clt)
+ | PC.TMetaLocalIdExp(_,_,_,_,clt) -> "localidexpmeta"^(line_type2c clt)
+ | PC.TMetaExpList(_,_,_,clt) -> "explistmeta"^(line_type2c clt)
+ | PC.TMetaId(_,_,_,clt) -> "idmeta"^(line_type2c clt)
+ | PC.TMetaType(_,_,clt) -> "typemeta"^(line_type2c clt)
+ | PC.TMetaStm(_,_,clt) -> "stmmeta"^(line_type2c clt)
+ | PC.TMetaStmList(_,_,clt) -> "stmlistmeta"^(line_type2c clt)
+ | PC.TMetaFunc(_,_,_,clt) -> "funcmeta"^(line_type2c clt)
+ | PC.TMetaLocalFunc(_,_,_,clt) -> "funcmeta"^(line_type2c clt)
+ | PC.TMetaPos(_,_,_,clt) -> "posmeta"
+ | PC.TMPtVirg -> ";"
+ | PC.TArobArob -> "@@"
+ | PC.TArob -> "@"
+ | PC.TPArob -> "P@"
+
+ | PC.TWhen(clt) -> "WHEN"^(line_type2c clt)
+ | PC.TAny(clt) -> "ANY"^(line_type2c clt)
+ | PC.TStrict(clt) -> "STRICT"^(line_type2c clt)
+ | PC.TEllipsis(clt) -> "..."^(line_type2c clt)
+(*
+ | PC.TCircles(clt) -> "ooo"^(line_type2c clt)
+ | PC.TStars(clt) -> "***"^(line_type2c clt)
+*)
+
+ | PC.TOEllipsis(clt) -> "<..."^(line_type2c clt)
+ | PC.TCEllipsis(clt) -> "...>"^(line_type2c clt)
+ | PC.TPOEllipsis(clt) -> "<+..."^(line_type2c clt)
+ | PC.TPCEllipsis(clt) -> "...+>"^(line_type2c clt)
+(*
+ | PC.TOCircles(clt) -> "<ooo"^(line_type2c clt)
+ | PC.TCCircles(clt) -> "ooo>"^(line_type2c clt)
+ | PC.TOStars(clt) -> "<***"^(line_type2c clt)
+ | PC.TCStars(clt) -> "***>"^(line_type2c clt)
+*)
+ | PC.TBang0 -> "!"
+ | PC.TPlus0 -> "+"
+ | PC.TWhy0 -> "?"
+
+ | PC.TWhy(clt) -> "?"^(line_type2c clt)
+ | PC.TDotDot(clt) -> ":"^(line_type2c clt)
+ | PC.TBang(clt) -> "!"^(line_type2c clt)
+ | PC.TOPar(clt) -> "("^(line_type2c clt)
+ | PC.TOPar0(clt) -> "("^(line_type2c clt)
+ | PC.TMid0(clt) -> "|"^(line_type2c clt)
+ | PC.TCPar(clt) -> ")"^(line_type2c clt)
+ | PC.TCPar0(clt) -> ")"^(line_type2c clt)
+
+ | PC.TOBrace(clt) -> "{"^(line_type2c clt)
+ | PC.TCBrace(clt) -> "}"^(line_type2c clt)
+ | PC.TOCro(clt) -> "["^(line_type2c clt)
+ | PC.TCCro(clt) -> "]"^(line_type2c clt)
+
+ | PC.TPtrOp(clt) -> "->"^(line_type2c clt)
+
+ | PC.TEq(clt) -> "="^(line_type2c clt)
+ | PC.TAssign(_,clt) -> "=op"^(line_type2c clt)
+ | PC.TDot(clt) -> "."^(line_type2c clt)
+ | PC.TComma(clt) -> ","^(line_type2c clt)
+ | PC.TPtVirg(clt) -> ";"^(line_type2c clt)
+
+ | PC.EOF -> "eof"
+ | PC.TLineEnd(clt) -> "line end"
+ | PC.TInvalid -> "invalid"
+ | PC.TFunDecl(clt) -> "fundecl"
+
+ | PC.TIso -> "<=>"
+ | PC.TRightIso -> "=>"
+ | PC.TIsoTopLevel -> "TopLevel"
+ | PC.TIsoExpression -> "Expression"
+ | PC.TIsoArgExpression -> "ArgExpression"
+ | PC.TIsoTestExpression -> "TestExpression"
+ | PC.TIsoStatement -> "Statement"
+ | PC.TIsoDeclaration -> "Declaration"
+ | PC.TIsoType -> "Type"
+ | PC.TScriptData s -> s
+
+let print_tokens s tokens =
+ Printf.printf "%s\n" s;
+ List.iter (function x -> Printf.printf "%s " (token2c x)) tokens;
+ Printf.printf "\n\n";
+ flush stdout
+
+type plus = PLUS | NOTPLUS | SKIP
+
+let plus_attachable (tok,_) =
+ match tok with
+ PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt) | PC.Tstatic(clt)
+ | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt)
+ | PC.Tauto(clt) | PC.Tregister(clt)
+ | PC.Textern(clt) | PC.Tconst(clt) | PC.Tvolatile(clt)
+
+ | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TDefine(clt,_)
+ | PC.TDefineParam(clt,_,_) | PC.TMinusFile(_,clt) | PC.TPlusFile(_,clt)
+
+ | PC.TInc(clt) | PC.TDec(clt)
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch(clt) | PC.TCase(clt) | PC.TDefault(clt) | PC.TReturn(clt)
+ | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt) | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+
+ | PC.TSizeof(clt)
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt)
+
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaErr(_,_,_,clt)
+ | PC.TMetaExp(_,_,_,_,clt) | PC.TMetaIdExp(_,_,_,_,clt)
+ | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt)
+ | PC.TMetaType(_,_,clt) | PC.TMetaStm(_,_,clt)
+ | PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
+ | PC.TMetaLocalFunc(_,_,_,clt)
+
+ | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ (* | PC.TCircles(clt) | PC.TStars(clt) *)
+
+ | PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
+ | PC.TCPar(clt)
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+
+ | PC.TPtrOp(clt)
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt) ->
+ if line_type clt = D.PLUS then PLUS else NOTPLUS
+
+ | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar0(clt)
+ | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+ | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (* | PC.TOCircles(clt)
+ | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *) -> NOTPLUS
+ | PC.TMetaPos(nm,_,_,_) -> NOTPLUS
+
+ | _ -> SKIP
+
+let get_clt (tok,_) =
+ match tok with
+ PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt) | PC.Tstatic(clt)
+ | PC.Tinline(clt) | PC.Tattr(_,clt) | PC.Tauto(clt) | PC.Tregister(clt)
+ | PC.Textern(clt) | PC.Tconst(clt) | PC.Tvolatile(clt)
+
+ | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TDefine(clt,_)
+ | PC.TDefineParam(clt,_,_) | PC.TMinusFile(_,clt) | PC.TPlusFile(_,clt)
+
+ | PC.TInc(clt) | PC.TDec(clt)
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch(clt) | PC.TCase(clt) | PC.TDefault(clt) | PC.TReturn(clt)
+ | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt) | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+
+ | PC.TSizeof(clt)
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt)
+
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaErr(_,_,_,clt)
+ | PC.TMetaExp(_,_,_,_,clt) | PC.TMetaIdExp(_,_,_,_,clt)
+ | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt)
+ | PC.TMetaType(_,_,clt) | PC.TMetaStm(_,_,clt)
+ | PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
+ | PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
+
+ | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ (* | PC.TCircles(clt) | PC.TStars(clt) *)
+
+ | PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
+ | PC.TCPar(clt)
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+
+ | PC.TPtrOp(clt)
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt)
+
+ | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar0(clt)
+ | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+ | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (* | PC.TOCircles(clt)
+ | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *) -> clt
+
+ | _ -> failwith "no clt"
+
+let update_clt (tok,x) clt =
+ match tok with
+ PC.Tchar(_) -> (PC.Tchar(clt),x)
+ | PC.Tshort(_) -> (PC.Tshort(clt),x)
+ | PC.Tint(_) -> (PC.Tint(clt),x)
+ | PC.Tdouble(_) -> (PC.Tdouble(clt),x)
+ | PC.Tfloat(_) -> (PC.Tfloat(clt),x)
+ | PC.Tlong(_) -> (PC.Tlong(clt),x)
+ | PC.Tvoid(_) -> (PC.Tvoid(clt),x)
+ | PC.Tstruct(_) -> (PC.Tstruct(clt),x)
+ | PC.Tunion(_) -> (PC.Tunion(clt),x)
+ | PC.Tunsigned(_) -> (PC.Tunsigned(clt),x)
+ | PC.Tsigned(_) -> (PC.Tsigned(clt),x)
+ | PC.Tstatic(_) -> (PC.Tstatic(clt),x)
+ | PC.Tinline(_) -> (PC.Tinline(clt),x)
+ | PC.Ttypedef(_) -> (PC.Ttypedef(clt),x)
+ | PC.Tattr(s,_) -> (PC.Tattr(s,clt),x)
+ | PC.Tauto(_) -> (PC.Tauto(clt),x)
+ | PC.Tregister(_) -> (PC.Tregister(clt),x)
+ | PC.Textern(_) -> (PC.Textern(clt),x)
+ | PC.Tconst(_) -> (PC.Tconst(clt),x)
+ | PC.Tvolatile(_) -> (PC.Tvolatile(clt),x)
+
+ | PC.TIncludeL(s,_) -> (PC.TIncludeL(s,clt),x)
+ | PC.TIncludeNL(s,_) -> (PC.TIncludeNL(s,clt),x)
+ | PC.TDefine(_,a) -> (PC.TDefine(clt,a),x)
+ | PC.TDefineParam(_,a,b) -> (PC.TDefineParam(clt,a,b),x)
+ | PC.TMinusFile(s,_) -> (PC.TMinusFile(s,clt),x)
+ | PC.TPlusFile(s,_) -> (PC.TPlusFile(s,clt),x)
+
+ | PC.TInc(_) -> (PC.TInc(clt),x)
+ | PC.TDec(_) -> (PC.TDec(clt),x)
+
+ | PC.TIf(_) -> (PC.TIf(clt),x)
+ | PC.TElse(_) -> (PC.TElse(clt),x)
+ | PC.TWhile(_) -> (PC.TWhile(clt),x)
+ | PC.TFor(_) -> (PC.TFor(clt),x)
+ | PC.TDo(_) -> (PC.TDo(clt),x)
+ | PC.TSwitch(_) -> (PC.TSwitch(clt),x)
+ | PC.TCase(_) -> (PC.TCase(clt),x)
+ | PC.TDefault(_) -> (PC.TDefault(clt),x)
+ | PC.TReturn(_) -> (PC.TReturn(clt),x)
+ | PC.TBreak(_) -> (PC.TBreak(clt),x)
+ | PC.TContinue(_) -> (PC.TContinue(clt),x)
+ | PC.TGoto(_) -> (PC.TGoto(clt),x)
+ | PC.TIdent(s,_) -> (PC.TIdent(s,clt),x)
+ | PC.TTypeId(s,_) -> (PC.TTypeId(s,clt),x)
+ | PC.TDeclarerId(s,_) -> (PC.TDeclarerId(s,clt),x)
+ | PC.TIteratorId(s,_) -> (PC.TIteratorId(s,clt),x)
+
+ | PC.TSizeof(_) -> (PC.TSizeof(clt),x)
+
+ | PC.TString(s,_) -> (PC.TString(s,clt),x)
+ | PC.TChar(s,_) -> (PC.TChar(s,clt),x)
+ | PC.TFloat(s,_) -> (PC.TFloat(s,clt),x)
+ | PC.TInt(s,_) -> (PC.TInt(s,clt),x)
+
+ | PC.TOrLog(_) -> (PC.TOrLog(clt),x)
+ | PC.TAndLog(_) -> (PC.TAndLog(clt),x)
+ | PC.TOr(_) -> (PC.TOr(clt),x)
+ | PC.TXor(_) -> (PC.TXor(clt),x)
+ | PC.TAnd (_) -> (PC.TAnd (clt),x)
+ | PC.TEqEq(_) -> (PC.TEqEq(clt),x)
+ | PC.TNotEq(_) -> (PC.TNotEq(clt),x)
+ | PC.TLogOp(op,_) -> (PC.TLogOp(op,clt),x)
+ | PC.TShOp(op,_) -> (PC.TShOp(op,clt),x)
+ | PC.TPlus(_) -> (PC.TPlus(clt),x)
+ | PC.TMinus(_) -> (PC.TMinus(clt),x)
+ | PC.TMul(_) -> (PC.TMul(clt),x)
+ | PC.TDmOp(op,_) -> (PC.TDmOp(op,clt),x)
+ | PC.TTilde (_) -> (PC.TTilde (clt),x)
+
+ | PC.TMetaParam(a,b,_) -> (PC.TMetaParam(a,b,clt),x)
+ | PC.TMetaParamList(a,b,c,_) -> (PC.TMetaParamList(a,b,c,clt),x)
+ | PC.TMetaConst(a,b,c,d,_) -> (PC.TMetaConst(a,b,c,d,clt),x)
+ | PC.TMetaErr(a,b,c,_) -> (PC.TMetaErr(a,b,c,clt),x)
+ | PC.TMetaExp(a,b,c,d,_) -> (PC.TMetaExp(a,b,c,d,clt),x)
+ | PC.TMetaIdExp(a,b,c,d,_) -> (PC.TMetaIdExp(a,b,c,d,clt),x)
+ | PC.TMetaLocalIdExp(a,b,c,d,_) -> (PC.TMetaLocalIdExp(a,b,c,d,clt),x)
+ | PC.TMetaExpList(a,b,c,_) -> (PC.TMetaExpList(a,b,c,clt),x)
+ | PC.TMetaId(a,b,c,_) -> (PC.TMetaId(a,b,c,clt),x)
+ | PC.TMetaType(a,b,_) -> (PC.TMetaType(a,b,clt),x)
+ | PC.TMetaStm(a,b,_) -> (PC.TMetaStm(a,b,clt),x)
+ | PC.TMetaStmList(a,b,_) -> (PC.TMetaStmList(a,b,clt),x)
+ | PC.TMetaFunc(a,b,c,_) -> (PC.TMetaFunc(a,b,c,clt),x)
+ | PC.TMetaLocalFunc(a,b,c,_) -> (PC.TMetaLocalFunc(a,b,c,clt),x)
+
+ | PC.TWhen(_) -> (PC.TWhen(clt),x)
+ | PC.TAny(_) -> (PC.TAny(clt),x)
+ | PC.TStrict(_) -> (PC.TStrict(clt),x)
+ | PC.TEllipsis(_) -> (PC.TEllipsis(clt),x)
+(*
+ | PC.TCircles(_) -> (PC.TCircles(clt),x)
+ | PC.TStars(_) -> (PC.TStars(clt),x)
+*)
+
+ | PC.TOEllipsis(_) -> (PC.TOEllipsis(clt),x)
+ | PC.TCEllipsis(_) -> (PC.TCEllipsis(clt),x)
+ | PC.TPOEllipsis(_) -> (PC.TPOEllipsis(clt),x)
+ | PC.TPCEllipsis(_) -> (PC.TPCEllipsis(clt),x)
+(*
+ | PC.TOCircles(_) -> (PC.TOCircles(clt),x)
+ | PC.TCCircles(_) -> (PC.TCCircles(clt),x)
+ | PC.TOStars(_) -> (PC.TOStars(clt),x)
+ | PC.TCStars(_) -> (PC.TCStars(clt),x)
+*)
+
+ | PC.TWhy(_) -> (PC.TWhy(clt),x)
+ | PC.TDotDot(_) -> (PC.TDotDot(clt),x)
+ | PC.TBang(_) -> (PC.TBang(clt),x)
+ | PC.TOPar(_) -> (PC.TOPar(clt),x)
+ | PC.TOPar0(_) -> (PC.TOPar0(clt),x)
+ | PC.TMid0(_) -> (PC.TMid0(clt),x)
+ | PC.TCPar(_) -> (PC.TCPar(clt),x)
+ | PC.TCPar0(_) -> (PC.TCPar0(clt),x)
+
+ | PC.TOBrace(_) -> (PC.TOBrace(clt),x)
+ | PC.TCBrace(_) -> (PC.TCBrace(clt),x)
+ | PC.TOCro(_) -> (PC.TOCro(clt),x)
+ | PC.TCCro(_) -> (PC.TCCro(clt),x)
+
+ | PC.TPtrOp(_) -> (PC.TPtrOp(clt),x)
+
+ | PC.TEq(_) -> (PC.TEq(clt),x)
+ | PC.TAssign(s,_) -> (PC.TAssign(s,clt),x)
+ | PC.TDot(_) -> (PC.TDot(clt),x)
+ | PC.TComma(_) -> (PC.TComma(clt),x)
+ | PC.TPtVirg(_) -> (PC.TPtVirg(clt),x)
+
+ | PC.TLineEnd(_) -> (PC.TLineEnd(clt),x)
+ | PC.TFunDecl(_) -> (PC.TFunDecl(clt),x)
+
+ | _ -> failwith "no clt"
+
+
+(* ----------------------------------------------------------------------- *)
+
+let make_name prefix ln = Printf.sprintf "%s starting on line %d" prefix ln
+
+(* ----------------------------------------------------------------------- *)
+(* Read tokens *)
+
+let wrap_lexbuf_info lexbuf =
+ (Lexing.lexeme lexbuf, Lexing.lexeme_start lexbuf)
+
+let tokens_all_full token table file get_ats lexbuf end_markers :
+ (bool * ((PC.token * (string * (int * int) * (int * int))) list)) =
+ try
+ let rec aux () =
+ let result = token lexbuf in
+ let info = (Lexing.lexeme lexbuf,
+ (table.(Lexing.lexeme_start lexbuf)),
+ (Lexing.lexeme_start lexbuf, Lexing.lexeme_end lexbuf)) in
+ if result = PC.EOF
+ then
+ if get_ats
+ then failwith "unexpected end of file in a metavariable declaration"
+ else (false,[(result,info)])
+ else if List.mem result end_markers
+ then (true,[(result,info)])
+ else
+ let (more,rest) = aux() in
+ (more,(result, info)::rest)
+ in aux ()
+ with
+ e -> pr2 (Common.error_message file (wrap_lexbuf_info lexbuf) ); raise e
+
+let tokens_all table file get_ats lexbuf end_markers :
+ (bool * ((PC.token * (string * (int * int) * (int * int))) list)) =
+ tokens_all_full Lexer_cocci.token table file get_ats lexbuf end_markers
+
+let tokens_script_all table file get_ats lexbuf end_markers :
+ (bool * ((PC.token * (string * (int * int) * (int * int))) list)) =
+ tokens_all_full Lexer_script.token table file get_ats lexbuf end_markers
+
+(* ----------------------------------------------------------------------- *)
+(* Split tokens into minus and plus fragments *)
+
+let split t clt =
+ let (d,_,_,_,_,_,_,_) = clt in
+ match d with
+ D.MINUS | D.OPTMINUS | D.UNIQUEMINUS -> ([t],[])
+ | D.PLUS -> ([],[t])
+ | D.CONTEXT | D.UNIQUE | D.OPT -> ([t],[t])
+
+let split_token ((tok,_) as t) =
+ match tok with
+ PC.TIdentifier | PC.TConstant | PC.TExpression | PC.TIdExpression
+ | PC.TStatement | PC.TPosition | PC.TPosAny
+ | PC.TFunction | PC.TTypedef | PC.TDeclarer | PC.TIterator | PC.TName
+ | PC.TType | PC.TParameter | PC.TLocal | PC.Tlist | PC.TFresh | PC.TPure
+ | PC.TContext | PC.TRuleName(_) | PC.TUsing | PC.TDisable | PC.TExtends
+ | PC.TPathIsoFile(_)
+ | PC.TDepends | PC.TOn | PC.TEver | PC.TNever | PC.TExists | PC.TForall
+ | PC.TReverse
+ | PC.TError | PC.TWords | PC.TNothing -> ([t],[t])
+
+ | PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
+ | PC.Tstatic(clt) | PC.Tauto(clt) | PC.Tregister(clt) | PC.Textern(clt)
+ | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt)
+ | PC.Tconst(clt) | PC.Tvolatile(clt) -> split t clt
+
+ | PC.TPragma(s) -> ([],[t]) (* only allowed in + *)
+ | PC.TPlusFile(s,clt) | PC.TMinusFile(s,clt)
+ | PC.TIncludeL(s,clt) | PC.TIncludeNL(s,clt) ->
+ split t clt
+ | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_) -> split t clt
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch(clt) | PC.TCase(clt) | PC.TDefault(clt)
+ | PC.TSizeof(clt)
+ | PC.TReturn(clt) | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt)
+ | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaExp(_,_,_,_,clt)
+ | PC.TMetaIdExp(_,_,_,_,clt) | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt) | PC.TMetaType(_,_,clt)
+ | PC.TMetaStm(_,_,clt) | PC.TMetaStmList(_,_,clt) | PC.TMetaErr(_,_,_,clt)
+ | PC.TMetaFunc(_,_,_,clt) | PC.TMetaLocalFunc(_,_,_,clt)
+ | PC.TMetaDeclarer(_,_,_,clt) | PC.TMetaIterator(_,_,_,clt) -> split t clt
+ | PC.TMPtVirg | PC.TArob | PC.TArobArob -> ([t],[t])
+ | PC.TPArob | PC.TMetaPos(_,_,_,_) -> ([t],[])
+
+ | PC.TFunDecl(clt)
+ | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TLineEnd(clt)
+ | PC.TEllipsis(clt) (* | PC.TCircles(clt) | PC.TStars(clt) *) -> split t clt
+
+ | PC.TOEllipsis(_) | PC.TCEllipsis(_) (* clt must be context *)
+ | PC.TPOEllipsis(_) | PC.TPCEllipsis(_) (* clt must be context *)
+(*
+ | PC.TOCircles(_) | PC.TCCircles(_) (* clt must be context *)
+ | PC.TOStars(_) | PC.TCStars(_) (* clt must be context *)
+*)
+ | PC.TBang0 | PC.TPlus0 | PC.TWhy0 ->
+ ([t],[t])
+
+ | PC.TWhy(clt) | PC.TDotDot(clt)
+ | PC.TBang(clt) | PC.TOPar(clt) | PC.TOPar0(clt)
+ | PC.TMid0(clt) | PC.TCPar(clt) | PC.TCPar0(clt) -> split t clt
+
+ | PC.TInc(clt) | PC.TDec(clt) -> split t clt
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt) ->
+ split t clt
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt) -> split t clt
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) -> split t clt
+ | PC.TOCro(clt) | PC.TCCro(clt) -> split t clt
+
+ | PC.TPtrOp(clt) -> split t clt
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt) -> split t clt
+
+ | PC.EOF | PC.TInvalid -> ([t],[t])
+
+ | PC.TIso | PC.TRightIso
+ | PC.TIsoExpression | PC.TIsoStatement | PC.TIsoDeclaration | PC.TIsoType
+ | PC.TIsoTopLevel | PC.TIsoArgExpression | PC.TIsoTestExpression ->
+ failwith "unexpected tokens"
+ | PC.TScriptData s -> ([t],[t])
+
+let split_token_stream tokens =
+ let rec loop = function
+ [] -> ([],[])
+ | token::tokens ->
+ let (minus,plus) = split_token token in
+ let (minus_stream,plus_stream) = loop tokens in
+ (minus@minus_stream,plus@plus_stream) in
+ loop tokens
+
+(* ----------------------------------------------------------------------- *)
+(* Find function names *)
+(* This addresses a shift-reduce problem in the parser, allowing us to
+distinguish a function declaration from a function call even if the latter
+has no return type. Undoubtedly, this is not very nice, but it doesn't
+seem very convenient to refactor the grammar to get around the problem. *)
+
+let rec find_function_names = function
+ [] -> []
+ | ((PC.TIdent(_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
+ | ((PC.TMetaId(_,_,_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
+ | ((PC.TMetaFunc(_,_,_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
+ | ((PC.TMetaLocalFunc(_,_,_,clt),info) as t1)::((PC.TOPar(_),_) as t2)::rest
+ ->
+ let rec skip level = function
+ [] -> ([],false,[])
+ | ((PC.TCPar(_),_) as t)::rest ->
+ let level = level - 1 in
+ if level = 0
+ then ([t],true,rest)
+ else let (pre,found,post) = skip level rest in (t::pre,found,post)
+ | ((PC.TOPar(_),_) as t)::rest ->
+ let level = level + 1 in
+ let (pre,found,post) = skip level rest in (t::pre,found,post)
+ | ((PC.TArobArob,_) as t)::rest
+ | ((PC.TArob,_) as t)::rest
+ | ((PC.EOF,_) as t)::rest -> ([t],false,rest)
+ | t::rest ->
+ let (pre,found,post) = skip level rest in (t::pre,found,post) in
+ let (pre,found,post) = skip 1 rest in
+ (match (found,post) with
+ (true,((PC.TOBrace(_),_) as t3)::rest) ->
+ (PC.TFunDecl(clt),info) :: t1 :: t2 :: pre @
+ t3 :: (find_function_names rest)
+ | _ -> t1 :: t2 :: pre @ find_function_names post)
+ | t :: rest -> t :: find_function_names rest
+
+(* ----------------------------------------------------------------------- *)
+(* an attribute is an identifier that preceeds another identifier and
+ begins with __ *)
+
+let rec detect_attr l =
+ let is_id = function
+ (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
+ | (PC.TMetaLocalFunc(_,_,_,_),_) -> true
+ | _ -> false in
+ let rec loop = function
+ [] -> []
+ | [x] -> [x]
+ | ((PC.TIdent(nm,clt),info) as t1)::id::rest when is_id id ->
+ if String.length nm > 2 && String.sub nm 0 2 = "__"
+ then (PC.Tattr(nm,clt),info)::(loop (id::rest))
+ else t1::(loop (id::rest))
+ | x::xs -> x::(loop xs) in
+ loop l
+
+(* ----------------------------------------------------------------------- *)
+(* Look for variable declarations where the name is a typedef name.
+We assume that C code does not contain a multiplication as a top-level
+statement. *)
+
+(* bug: once a type, always a type, even if the same name is later intended
+ to be used as a real identifier *)
+let detect_types in_meta_decls l =
+ let is_delim infn = function
+ (PC.TOEllipsis(_),_) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
+ | (PC.TPOEllipsis(_),_) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
+ | (PC.TEllipsis(_),_) (* | (PC.TCircles(_),_) | (PC.TStars(_),_) *)
+ | (PC.TPtVirg(_),_) | (PC.TOBrace(_),_) | (PC.TCBrace(_),_)
+ | (PC.TPure,_) | (PC.TContext,_)
+ | (PC.Tstatic(_),_) | (PC.Textern(_),_)
+ | (PC.Tinline(_),_) | (PC.Ttypedef(_),_) | (PC.Tattr(_),_) -> true
+ | (PC.TComma(_),_) when infn > 0 or in_meta_decls -> true
+ | (PC.TDotDot(_),_) when in_meta_decls -> true
+ | _ -> false in
+ let is_choices_delim = function
+ (PC.TOBrace(_),_) | (PC.TComma(_),_) -> true | _ -> false in
+ let is_id = function
+ (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
+ | (PC.TMetaLocalFunc(_,_,_,_),_) -> true
+ | (PC.TMetaParam(_,_,_),_)
+ | (PC.TMetaParamList(_,_,_,_),_)
+ | (PC.TMetaConst(_,_,_,_,_),_)
+ | (PC.TMetaErr(_,_,_,_),_)
+ | (PC.TMetaExp(_,_,_,_,_),_)
+ | (PC.TMetaIdExp(_,_,_,_,_),_)
+ | (PC.TMetaLocalIdExp(_,_,_,_,_),_)
+ | (PC.TMetaExpList(_,_,_,_),_)
+ | (PC.TMetaType(_,_,_),_)
+ | (PC.TMetaStm(_,_,_),_)
+ | (PC.TMetaStmList(_,_,_),_)
+ | (PC.TMetaPos(_,_,_,_),_) -> in_meta_decls
+ | _ -> false in
+ let redo_id ident clt v =
+ !Data.add_type_name ident;
+ (PC.TTypeId(ident,clt),v) in
+ let rec loop start infn type_names = function
+ (* infn: 0 means not in a function header
+ > 0 means in a function header, after infn - 1 unmatched open parens*)
+ [] -> []
+ | ((PC.TOBrace(clt),v)::_) as all when in_meta_decls ->
+ collect_choices type_names all (* never a function header *)
+ | delim::(PC.TIdent(ident,clt),v)::((PC.TMul(_),_) as x)::rest
+ when is_delim infn delim ->
+ let newid = redo_id ident clt v in
+ delim::newid::x::(loop false infn (ident::type_names) rest)
+ | delim::(PC.TIdent(ident,clt),v)::id::rest
+ when is_delim infn delim && is_id id ->
+ let newid = redo_id ident clt v in
+ delim::newid::id::(loop false infn (ident::type_names) rest)
+ | ((PC.TFunDecl(_),_) as fn)::rest ->
+ fn::(loop false 1 type_names rest)
+ | ((PC.TOPar(_),_) as lp)::rest when infn > 0 ->
+ lp::(loop false (infn + 1) type_names rest)
+ | ((PC.TCPar(_),_) as rp)::rest when infn > 0 ->
+ if infn - 1 = 1
+ then rp::(loop false 0 type_names rest) (* 0 means not in fn header *)
+ else rp::(loop false (infn - 1) type_names rest)
+ | (PC.TIdent(ident,clt),v)::((PC.TMul(_),_) as x)::rest when start ->
+ let newid = redo_id ident clt v in
+ newid::x::(loop false infn (ident::type_names) rest)
+ | (PC.TIdent(ident,clt),v)::id::rest when start && is_id id ->
+ let newid = redo_id ident clt v in
+ newid::id::(loop false infn (ident::type_names) rest)
+ | (PC.TIdent(ident,clt),v)::rest when List.mem ident type_names ->
+ (PC.TTypeId(ident,clt),v)::(loop false infn type_names rest)
+ | ((PC.TIdent(ident,clt),v) as x)::rest ->
+ x::(loop false infn type_names rest)
+ | x::rest -> x::(loop false infn type_names rest)
+ and collect_choices type_names = function
+ [] -> [] (* should happen, but let the parser detect that *)
+ | (PC.TCBrace(clt),v)::rest ->
+ (PC.TCBrace(clt),v)::(loop false 0 type_names rest)
+ | delim::(PC.TIdent(ident,clt),v)::rest
+ when is_choices_delim delim ->
+ let newid = redo_id ident clt v in
+ delim::newid::(collect_choices (ident::type_names) rest)
+ | x::rest -> x::(collect_choices type_names rest) in
+ loop true 0 [] l
+
+
+(* ----------------------------------------------------------------------- *)
+(* Insert TLineEnd tokens at the end of a line that contains a WHEN.
+ WHEN is restricted to a single line, to avoid ambiguity in eg:
+ ... WHEN != x
+ +3 *)
+
+let token2line (tok,_) =
+ match tok with
+ PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
+ | PC.Tstatic(clt) | PC.Tauto(clt) | PC.Tregister(clt) | PC.Textern(clt)
+ | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt) | PC.Tconst(clt)
+ | PC.Tvolatile(clt)
+
+ | PC.TInc(clt) | PC.TDec(clt)
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch (clt) | PC.TCase (clt) | PC.TDefault (clt) | PC.TSizeof (clt)
+ | PC.TReturn(clt) | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt)
+ | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+ | PC.TMetaDeclarer(_,_,_,clt) | PC.TMetaIterator(_,_,_,clt)
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt)
+
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaExp(_,_,_,_,clt)
+ | PC.TMetaIdExp(_,_,_,_,clt) | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt) | PC.TMetaType(_,_,clt)
+ | PC.TMetaStm(_,_,clt) | PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
+ | PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
+
+ | PC.TFunDecl(clt)
+ | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ (* | PC.TCircles(clt) | PC.TStars(clt) *)
+
+ | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+ | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (*| PC.TOCircles(clt)
+ | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *)
+
+ | PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
+ | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar(clt)
+ | PC.TCPar0(clt)
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+
+ | PC.TPtrOp(clt)
+
+ | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_)
+ | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt)
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt) ->
+ let (_,line,_,_,_,_,_,_) = clt in Some line
+
+ | _ -> None
+
+let rec insert_line_end = function
+ [] -> []
+ | (((PC.TWhen(clt),q) as x)::xs) ->
+ x::(find_line_end true (token2line x) clt q xs)
+ | (((PC.TDefine(clt,_),q) as x)::xs)
+ | (((PC.TDefineParam(clt,_,_),q) as x)::xs) ->
+ x::(find_line_end false (token2line x) clt q xs)
+ | x::xs -> x::(insert_line_end xs)
+
+and find_line_end inwhen line clt q = function
+ (* don't know what 2nd component should be so just use the info of
+ the When. Also inherit - of when, if any *)
+ [] -> [(PC.TLineEnd(clt),q)]
+ | ((PC.TIdent("strict",clt),a) as x)::xs when token2line x = line ->
+ (PC.TStrict(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("STRICT",clt),a) as x)::xs when token2line x = line ->
+ (PC.TStrict(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("any",clt),a) as x)::xs when token2line x = line ->
+ (PC.TAny(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("ANY",clt),a) as x)::xs when token2line x = line ->
+ (PC.TAny(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("forall",clt),a) as x)::xs when token2line x = line ->
+ (PC.TForall,a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("exists",clt),a) as x)::xs when token2line x = line ->
+ (PC.TExists,a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TComma(clt),a) as x)::xs when token2line x = line ->
+ (PC.TComma(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TPArob,a) as x)::xs -> (* no line #, just assume on the same line *)
+ x :: (find_line_end inwhen line clt q xs)
+ | x::xs when token2line x = line -> x :: (find_line_end inwhen line clt q xs)
+ | xs -> (PC.TLineEnd(clt),q)::(insert_line_end xs)
+
+(* ----------------------------------------------------------------------- *)
+(* process pragmas: they can only be used in + code, and adjacent to
+another + token. They are concatenated to the string representation of
+that other token. *)
+
+let rec collect_all_pragmas collected = function
+ (PC.TPragma(s),_)::rest -> collect_all_pragmas (s::collected) rest
+ | l -> (List.rev collected,l)
+
+let rec collect_up_to_pragmas skipped = function
+ [] -> None (* didn't reach a pragma, so nothing to do *)
+ | ((PC.TPragma(s),_) as t)::rest ->
+ let (pragmas,rest) = collect_all_pragmas [] (t::rest) in
+ Some (List.rev skipped,pragmas,rest)
+ | x::xs ->
+ match plus_attachable x with
+ PLUS -> None
+ | NOTPLUS -> None
+ | SKIP -> collect_up_to_pragmas (x::skipped) xs
+
+let rec collect_up_to_plus skipped = function
+ [] -> failwith "nothing to attach a pragma to"
+ | x::xs ->
+ match plus_attachable x with
+ PLUS -> (List.rev skipped,x,xs)
+ | NOTPLUS -> failwith "nothing to attach a pragma to"
+ | SKIP -> collect_up_to_plus (x::skipped) xs
+
+let rec process_pragmas = function
+ [] -> []
+ | ((PC.TPragma(s),_)::_) as l ->
+ let (pragmas,rest) = collect_all_pragmas [] l in
+ let (skipped,aft,rest) = collect_up_to_plus [] rest in
+ let (a,b,c,d,e,strbef,straft,pos) = get_clt aft in
+ skipped@
+ (process_pragmas ((update_clt aft (a,b,c,d,e,pragmas,straft,pos))::rest))
+ | bef::xs ->
+ (match plus_attachable bef with
+ PLUS ->
+ (match collect_up_to_pragmas [] xs with
+ Some(skipped,pragmas,rest) ->
+ let (a,b,c,d,e,strbef,straft,pos) = get_clt bef in
+ (update_clt bef (a,b,c,d,e,strbef,pragmas,pos))::
+ skipped@(process_pragmas rest)
+ | None -> bef::(process_pragmas xs))
+ | _ -> bef::(process_pragmas xs))
+
+(* ----------------------------------------------------------------------- *)
+(* Drop ... ... . This is only allowed in + code, and arises when there is
+some - code between the ... *)
+(* drop whens as well - they serve no purpose in + code and they cause
+problems for drop_double_dots *)
+
+let rec drop_when = function
+ [] -> []
+ | (PC.TWhen(clt),info)::xs ->
+ let rec loop = function
+ [] -> []
+ | (PC.TLineEnd(_),info)::xs -> drop_when xs
+ | x::xs -> loop xs in
+ loop xs
+ | x::xs -> x::drop_when xs
+
+(* instead of dropping the double dots, we put TNothing in between them.
+these vanish after the parser, but keeping all the ...s in the + code makes
+it easier to align the + and - code in context_neg and in preparation for the
+isomorphisms. This shouldn't matter because the context code of the +
+slice is mostly ignored anyway *)
+let rec drop_double_dots l =
+ let start = function
+ (PC.TOEllipsis(_),_) | (PC.TPOEllipsis(_),_)
+ (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *) ->
+ true
+ | _ -> false in
+ let middle = function
+ (PC.TEllipsis(_),_) (* | (PC.TCircles(_),_) | (PC.TStars(_),_) *) -> true
+ | _ -> false in
+ let final = function
+ (PC.TCEllipsis(_),_) | (PC.TPCEllipsis(_),_)
+ (* | (PC.TCCircles(_),_) | (PC.TCStars(_),_) *) ->
+ true
+ | _ -> false in
+ let rec loop ((_,i) as prev) = function
+ [] -> []
+ | x::rest when middle prev && middle x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest when start prev && middle x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest when start prev && final x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest when middle prev && final x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest -> x :: (loop x rest) in
+ match l with
+ [] -> []
+ | (x::xs) -> x :: loop x xs
+
+let rec fix f l =
+ let cur = f l in
+ if l = cur then l else fix f cur
+
+(* ( | ... | ) also causes parsing problems *)
+
+exception Not_empty
+
+let rec drop_empty_thing starter middle ender = function
+ [] -> []
+ | hd::rest when starter hd ->
+ let rec loop = function
+ x::rest when middle x -> loop rest
+ | x::rest when ender x -> rest
+ | _ -> raise Not_empty in
+ (match try Some(loop rest) with Not_empty -> None with
+ Some x -> drop_empty_thing starter middle ender x
+ | None -> hd :: drop_empty_thing starter middle ender rest)
+ | x::rest -> x :: drop_empty_thing starter middle ender rest
+
+let drop_empty_or =
+ drop_empty_thing
+ (function (PC.TOPar0(_),_) -> true | _ -> false)
+ (function (PC.TMid0(_),_) -> true | _ -> false)
+ (function (PC.TCPar0(_),_) -> true | _ -> false)
+
+let drop_empty_nest = drop_empty_thing
+
+(* ----------------------------------------------------------------------- *)
+(* Read tokens *)
+
+let get_s_starts (_, (s,_,(starts, ends))) =
+ Printf.printf "%d %d\n" starts ends; (s, starts)
+
+let pop2 l =
+ let v = List.hd !l in
+ l := List.tl !l;
+ v
+
+let reinit _ =
+ PC.reinit (function _ -> PC.TArobArob (* a handy token *))
+ (Lexing.from_function
+ (function buf -> function n -> raise Common.Impossible))
+
+let parse_one str parsefn file toks =
+ let all_tokens = ref toks in
+ let cur_tok = ref (List.hd !all_tokens) in
+
+ let lexer_function _ =
+ let (v, info) = pop2 all_tokens in
+ cur_tok := (v, info);
+ v in
+
+ let lexbuf_fake =
+ Lexing.from_function
+ (function buf -> function n -> raise Common.Impossible)
+ in
+
+ reinit();
+
+ try parsefn lexer_function lexbuf_fake
+ with
+ Lexer_cocci.Lexical s ->
+ failwith
+ (Printf.sprintf "%s: lexical error: %s\n =%s\n" str s
+ (Common.error_message file (get_s_starts !cur_tok) ))
+ | Parser_cocci_menhir.Error ->
+ failwith
+ (Printf.sprintf "%s: parse error: \n = %s\n" str
+ (Common.error_message file (get_s_starts !cur_tok) ))
+ | Semantic_cocci.Semantic s ->
+ failwith
+ (Printf.sprintf "%s: semantic error: %s\n =%s\n" str s
+ (Common.error_message file (get_s_starts !cur_tok) ))
+
+ | e -> raise e
+
+let prepare_tokens tokens =
+ insert_line_end
+ (detect_types false (find_function_names (detect_attr tokens)))
+
+let rec consume_minus_positions = function
+ [] -> []
+ | x::(PC.TPArob,_)::(PC.TMetaPos(name,constraints,per,clt),_)::xs ->
+ let (arity,ln,lln,offset,col,strbef,straft,_) = get_clt x in
+ let name = Parse_aux.clt2mcode name clt in
+ let x =
+ update_clt x
+ (arity,ln,lln,offset,col,strbef,straft,
+ Ast0.MetaPos(name,constraints,per)) in
+ x::(consume_minus_positions xs)
+ | x::xs -> x::consume_minus_positions xs
+
+let any_modif rule =
+ let mcode x =
+ match Ast0.get_mcode_mcodekind x with
+ Ast0.MINUS _ | Ast0.PLUS -> true
+ | _ -> false in
+ let donothing r k e = k e in
+ let bind x y = x or y in
+ let option_default = false in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing in
+ List.exists fn.V0.combiner_top_level rule
+
+let drop_last extra l = List.rev(extra@(List.tl(List.rev l)))
+
+let partition_either l =
+ let rec part_either left right = function
+ | [] -> (List.rev left, List.rev right)
+ | x :: l ->
+ (match x with
+ | Common.Left e -> part_either (e :: left) right l
+ | Common.Right e -> part_either left (e :: right) l) in
+ part_either [] [] l
+
+let get_metavars parse_fn table file lexbuf =
+ let rec meta_loop acc (* read one decl at a time *) =
+ let (_,tokens) =
+ tokens_all table file true lexbuf [PC.TArobArob;PC.TMPtVirg] in
+ let tokens = prepare_tokens tokens in
+ match tokens with
+ [(PC.TArobArob,_)] -> List.rev acc
+ | _ ->
+ let metavars = parse_one "meta" parse_fn file tokens in
+ meta_loop (metavars@acc) in
+ partition_either (meta_loop [])
+
+let get_script_metavars parse_fn table file lexbuf =
+ let rec meta_loop acc =
+ let (_, tokens) =
+ tokens_all table file true lexbuf [PC.TArobArob; PC.TMPtVirg] in
+ let tokens = prepare_tokens tokens in
+ match tokens with
+ [(PC.TArobArob, _)] -> List.rev acc
+ | _ ->
+ let metavar = parse_one "scriptmeta" parse_fn file tokens in
+ meta_loop (metavar :: acc)
+ in
+ meta_loop []
+
+let get_rule_name parse_fn starts_with_name get_tokens file prefix =
+ Data.in_rule_name := true;
+ let mknm _ = make_name prefix (!Lexer_cocci.line) in
+ let name_res =
+ if starts_with_name
+ then
+ let (_,tokens) = get_tokens [PC.TArob] in
+ match parse_one "rule name" parse_fn file tokens with
+ Ast.CocciRulename (None,a,b,c,d,e) ->
+ Ast.CocciRulename (Some (mknm()),a,b,c,d,e)
+ | Ast.CocciRulename (Some nm,a,b,c,d,e) ->
+ (if List.mem nm reserved_names
+ then failwith (Printf.sprintf "invalid name %s\n" nm));
+ Ast.CocciRulename (Some nm,a,b,c,d,e)
+ | Ast.ScriptRulename(s,deps) -> Ast.ScriptRulename(s,deps)
+ else
+ Ast.CocciRulename(Some(mknm()),Ast.NoDep,[],[],Ast.Undetermined,false) in
+ Data.in_rule_name := false;
+ name_res
+
+let parse_iso file =
+ let table = Common.full_charpos_to_pos file in
+ Common.with_open_infile file (fun channel ->
+ let lexbuf = Lexing.from_channel channel in
+ let get_tokens = tokens_all table file false lexbuf in
+ let res =
+ match get_tokens [PC.TArobArob;PC.TArob] with
+ (true,start) ->
+ let parse_start start =
+ let rev = List.rev start in
+ let (arob,_) = List.hd rev in
+ (arob = PC.TArob,List.rev(List.tl rev)) in
+ let (starts_with_name,start) = parse_start start in
+ let rec loop starts_with_name start =
+ (!Data.init_rule)();
+ (* get metavariable declarations - have to be read before the
+ rest *)
+ let (rule_name,_,_,_,_,_) =
+ match get_rule_name PC.iso_rule_name starts_with_name get_tokens
+ file ("iso file "^file) with
+ Ast.CocciRulename (Some n,a,b,c,d,e) -> (n,a,b,c,d,e)
+ | _ -> failwith "Script rules cannot appear in isomorphism rules"
+ in
+ Ast0.rule_name := rule_name;
+ Data.in_meta := true;
+ let iso_metavars =
+ match get_metavars PC.iso_meta_main table file lexbuf with
+ (iso_metavars,[]) -> iso_metavars
+ | _ -> failwith "unexpected inheritance in iso" in
+ Data.in_meta := false;
+ (* get the rule *)
+ let (more,tokens) =
+ get_tokens
+ [PC.TIsoStatement;PC.TIsoExpression;PC.TIsoArgExpression;
+ PC.TIsoTestExpression;
+ PC.TIsoDeclaration;PC.TIsoType;PC.TIsoTopLevel] in
+ let next_start = List.hd(List.rev tokens) in
+ let dummy_info = ("",(-1,-1),(-1,-1)) in
+ let tokens = drop_last [(PC.EOF,dummy_info)] tokens in
+ let tokens = prepare_tokens (start@tokens) in
+ (*
+ print_tokens "iso tokens" tokens;
+ *)
+ let entry = parse_one "iso main" PC.iso_main file tokens in
+ let entry = List.map (List.map Test_exps.process_anything) entry in
+ if more
+ then (* The code below allows a header like Statement list,
+ which is more than one word. We don't have that any more,
+ but the code is left here in case it is put back. *)
+ match get_tokens [PC.TArobArob;PC.TArob] with
+ (true,start) ->
+ let (starts_with_name,start) = parse_start start in
+ (iso_metavars,entry,rule_name) ::
+ (loop starts_with_name (next_start::start))
+ | _ -> failwith "isomorphism ends early"
+ else [(iso_metavars,entry,rule_name)] in
+ loop starts_with_name start
+ | (false,_) -> [] in
+ res)
+
+let parse_iso_files existing_isos iso_files extra_path =
+ let get_names = List.map (function (_,_,nm) -> nm) in
+ let old_names = get_names existing_isos in
+ Data.in_iso := true;
+ let (res,_) =
+ List.fold_left
+ (function (prev,names) ->
+ function file ->
+ Lexer_cocci.init ();
+ let file =
+ match file with
+ Common.Left(fl) -> Filename.concat extra_path fl
+ | Common.Right(fl) -> Filename.concat Config.path fl in
+ let current = parse_iso file in
+ let new_names = get_names current in
+ if List.exists (function x -> List.mem x names) new_names
+ then failwith (Printf.sprintf "repeated iso name found in %s" file);
+ (current::prev,new_names @ names))
+ ([],old_names) iso_files in
+ Data.in_iso := false;
+ existing_isos@(List.concat (List.rev res))
+
+let parse file =
+ let table = Common.full_charpos_to_pos file in
+ Common.with_open_infile file (fun channel ->
+ let lexbuf = Lexing.from_channel channel in
+ let get_tokens = tokens_all table file false lexbuf in
+ Data.in_prolog := true;
+ let initial_tokens = get_tokens [PC.TArobArob;PC.TArob] in
+ Data.in_prolog := false;
+ let res =
+ match initial_tokens with
+ (true,data) ->
+ (match List.rev data with
+ ((PC.TArobArob as x),_)::_ | ((PC.TArob as x),_)::_ ->
+ let iso_files =
+ parse_one "iso file names" PC.include_main file data in
+
+ let parse_cocci_rule old_metas
+ (rule_name, dependencies, iso, dropiso, exists, is_expression) =
+ Ast0.rule_name := rule_name;
+ Data.inheritable_positions :=
+ rule_name :: !Data.inheritable_positions;
+
+ (* get metavariable declarations *)
+ Data.in_meta := true;
+ let (metavars, inherited_metavars) =
+ get_metavars PC.meta_main table file lexbuf in
+ Data.in_meta := false;
+ Hashtbl.add Data.all_metadecls rule_name metavars;
+ Hashtbl.add Lexer_cocci.rule_names rule_name ();
+ Hashtbl.add Lexer_cocci.all_metavariables rule_name
+ (Hashtbl.fold
+ (fun key v rest -> (key,v)::rest)
+ Lexer_cocci.metavariables []);
+
+ (* get transformation rules *)
+ let (more, tokens) = get_tokens [PC.TArobArob; PC.TArob] in
+ let (minus_tokens, plus_tokens) = split_token_stream tokens in
+
+ let minus_tokens = consume_minus_positions minus_tokens in
+ let minus_tokens = prepare_tokens minus_tokens in
+ let plus_tokens = prepare_tokens plus_tokens in
+
+ (*
+ print_tokens "minus tokens" minus_tokens;
+ print_tokens "plus tokens" plus_tokens;
+ *)
+
+ let plus_tokens =
+ process_pragmas
+ (fix (function x -> drop_double_dots (drop_empty_or x))
+ (drop_when plus_tokens)) in
+ (*
+ print_tokens "plus tokens" plus_tokens;
+ Printf.printf "before minus parse\n";
+ *)
+ let minus_res =
+ if is_expression
+ then parse_one "minus" PC.minus_exp_main file minus_tokens
+ else parse_one "minus" PC.minus_main file minus_tokens in
+ (*
+ Unparse_ast0.unparse minus_res;
+ Printf.printf "before plus parse\n";
+ *)
+ let plus_res =
+ if !Flag.sgrep_mode2
+ then (* not actually used for anything, except context_neg *)
+ List.map
+ (Iso_pattern.rebuild_mcode None).V0.rebuilder_top_level
+ minus_res
+ else
+ if is_expression
+ then parse_one "plus" PC.plus_exp_main file plus_tokens
+ else parse_one "plus" PC.plus_main file plus_tokens in
+ (*
+ Printf.printf "after plus parse\n";
+ *)
+
+ (if not !Flag.sgrep_mode2 &&
+ (any_modif minus_res or any_modif plus_res)
+ then Data.inheritable_positions := []);
+
+ Check_meta.check_meta rule_name old_metas inherited_metavars
+ metavars minus_res plus_res;
+
+ (more, Ast0.CocciRule ((minus_res, metavars,
+ (iso, dropiso, dependencies, rule_name, exists)),
+ (plus_res, metavars)), metavars, tokens) in
+
+ let parse_script_rule language old_metas deps =
+ let get_tokens = tokens_script_all table file false lexbuf in
+
+ (* meta-variables *)
+ Data.in_meta := true;
+ let metavars =
+ get_script_metavars PC.script_meta_main table file lexbuf in
+ Data.in_meta := false;
+
+ let exists_in old_metas (py,(r,m)) =
+ let test (rr,mr) x =
+ let (ro,vo) = Ast.get_meta_name x in
+ ro = rr && vo = mr in
+ List.exists (test (r,m)) old_metas in
+
+ List.iter
+ (function x ->
+ let meta2c (r,n) = Printf.sprintf "%s.%s" r n in
+ if not (exists_in old_metas x) then
+ failwith
+ (Printf.sprintf
+ "Script references unknown meta-variable: %s"
+ (meta2c(snd x))))
+ metavars;
+
+ (* script code *)
+ let (more, tokens) = get_tokens [PC.TArobArob; PC.TArob] in
+ let data =
+ match List.hd tokens with
+ (PC.TScriptData(s),_) -> s
+ | (PC.TArobArob,_) | (PC.TArob,_) -> ""
+ | _ -> failwith "Malformed script rule" in
+ (more,Ast0.ScriptRule(language, deps, metavars, data),[],tokens) in
+
+ let parse_rule old_metas starts_with_name =
+ let rulename =
+ get_rule_name PC.rule_name starts_with_name get_tokens file
+ "rule" in
+ match rulename with
+ Ast.CocciRulename (Some s, a, b, c, d, e) ->
+ parse_cocci_rule old_metas (s, a, b, c, d, e)
+ | Ast.ScriptRulename (l,deps) -> parse_script_rule l old_metas deps
+ | _ -> failwith "Malformed rule name"
+ in
+
+ let rec loop old_metas starts_with_name =
+ (!Data.init_rule)();
+
+ let gen_starts_with_name more tokens =
+ more &&
+ (match List.hd (List.rev tokens) with
+ (PC.TArobArob,_) -> false
+ | (PC.TArob,_) -> true
+ | _ -> failwith "unexpected token")
+ in
+
+ let (more, rule, metavars, tokens) =
+ parse_rule old_metas starts_with_name in
+ if more then
+ rule::
+ (loop (metavars @ old_metas) (gen_starts_with_name more tokens))
+ else [rule];
+
+ in
+
+ (iso_files, loop [] (x = PC.TArob))
+ | _ -> failwith "unexpected code before the first rule\n")
+ | (false,[(PC.TArobArob,_)]) | (false,[(PC.TArob,_)]) ->
+ ([],([] : Ast0.parsed_rule list))
+ | _ -> failwith "unexpected code before the first rule\n" in
+ res)
+
+(* parse to ast0 and then convert to ast *)
+let process file isofile verbose =
+ let extra_path = Filename.dirname file in
+ Lexer_cocci.init();
+ let (iso_files, rules) = parse file in
+ let std_isos =
+ match isofile with
+ None -> []
+ | Some iso_file -> parse_iso_files [] [Common.Left iso_file] "" in
+ let global_isos = parse_iso_files std_isos iso_files extra_path in
+ let rules = Unitary_ast0.do_unitary rules in
+ let parsed =
+ List.map
+ (function
+ Ast0.ScriptRule (a,b,c,d) -> [([],Ast.ScriptRule (a,b,c,d))]
+ | Ast0.CocciRule
+ ((minus, metavarsm,
+ (iso, dropiso, dependencies, rule_name, exists)),
+ (plus, metavars)) ->
+ let chosen_isos =
+ parse_iso_files global_isos
+ (List.map (function x -> Common.Left x) iso)
+ extra_path in
+ let chosen_isos =
+ (* check that dropped isos are actually available *)
+ (try
+ let iso_names =
+ List.map (function (_,_,nm) -> nm) chosen_isos in
+ let local_iso_names = reserved_names @ iso_names in
+ let bad_dropped =
+ List.find
+ (function dropped ->
+ not (List.mem dropped local_iso_names))
+ dropiso in
+ failwith
+ ("invalid iso name " ^ bad_dropped ^ " in " ^ rule_name)
+ with Not_found -> ());
+ if List.mem "all" dropiso
+ then
+ if List.length dropiso = 1
+ then []
+ else failwith "disable all should only be by itself"
+ else (* drop those isos *)
+ List.filter
+ (function (_,_,nm) -> not (List.mem nm dropiso))
+ chosen_isos in
+ List.iter Iso_compile.process chosen_isos;
+ let dropped_isos =
+ match reserved_names with
+ "all"::others ->
+ (match dropiso with
+ ["all"] -> others
+ | _ ->
+ List.filter (function x -> List.mem x dropiso) others)
+ | _ ->
+ failwith
+ "bad list of reserved names - all must be at start" in
+ let minus = Test_exps.process minus in
+ let minus = Compute_lines.compute_lines minus in
+ let plus = Compute_lines.compute_lines plus in
+ let is_exp =
+ (* only relevant to Flag.make_hrule *)
+ (* doesn't handle multiple minirules properly, but since
+ we don't really handle them in lots of other ways, it
+ doesn't seem very important *)
+ match plus with
+ [] -> [false]
+ | p::_ ->
+ [match Ast0.unwrap p with
+ Ast0.CODE c ->
+ (match List.map Ast0.unwrap (Ast0.undots c) with
+ [Ast0.Exp e] -> true | _ -> false)
+ | _ -> false] in
+ let minus = Arity.minus_arity minus in
+ let ((metavars,minus),function_prototypes) =
+ Function_prototypes.process
+ rule_name metavars dropped_isos minus plus in
+ (* warning! context_neg side-effects its arguments *)
+ let (m,p) = List.split (Context_neg.context_neg minus plus) in
+ Type_infer.type_infer p;
+ (if not !Flag.sgrep_mode2 then Insert_plus.insert_plus m p);
+ Type_infer.type_infer minus;
+ let (extra_meta, minus) =
+ Iso_pattern.apply_isos chosen_isos minus rule_name in
+ let minus = Comm_assoc.comm_assoc minus rule_name dropiso in
+ let minus =
+ if !Flag.sgrep_mode2 then minus
+ else Single_statement.single_statement minus in
+ let minus = Simple_assignments.simple_assignments minus in
+ let minus_ast =
+ Ast0toast.ast0toast rule_name dependencies dropped_isos
+ exists minus is_exp in
+ match function_prototypes with
+ None -> [(extra_meta @ metavars, minus_ast)]
+ | Some mv_fp ->
+ [(extra_meta @ metavars, minus_ast); mv_fp])
+(* Ast0.CocciRule ((minus, metavarsm, (iso, dropiso, dependencies, rule_name, exists)), (plus, metavars))*)
+ rules in
+ let parsed = List.concat parsed in
+ let disjd = Disjdistr.disj parsed in
+
+ let (code,fvs,neg_pos,ua,pos) = Free_vars.free_vars disjd in
+ if !Flag_parsing_cocci.show_SP
+ then List.iter Pretty_print_cocci.unparse code;
+
+ let grep_tokens =
+ Common.profile_code "get_constants"
+ (fun () -> Get_constants.get_constants code) in (* for grep *)
+ let glimpse_tokens2 =
+ Common.profile_code "get_glimpse_constants"
+ (fun () -> Get_constants2.get_constants code neg_pos) in(* for glimpse *)
+ (code,fvs,neg_pos,ua,pos,grep_tokens,glimpse_tokens2)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* splits the entire file into minus and plus fragments, and parses each
+separately (thus duplicating work for the parsing of the context elements) *)
+
+module D = Data
+module PC = Parser_cocci_menhir
+module V0 = Visitor_ast0
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+let pr = Printf.sprintf
+(*let pr2 s = prerr_string s; prerr_string "\n"; flush stderr*)
+let pr2 s = Printf.printf "%s\n" s
+
+(* for isomorphisms. all should be at the front!!! *)
+let reserved_names =
+ ["all";"optional_storage";"optional_qualifier";"value_format";"comm_assoc"]
+
+(* ----------------------------------------------------------------------- *)
+(* Debugging... *)
+
+let line_type (d,_,_,_,_,_,_,_) = d
+
+let line_type2c tok =
+ match line_type tok with
+ D.MINUS | D.OPTMINUS | D.UNIQUEMINUS -> ":-"
+ | D.PLUS -> ":+"
+ | D.CONTEXT | D.UNIQUE | D.OPT -> ""
+
+let token2c (tok,_) =
+ match tok with
+ PC.TIdentifier -> "identifier"
+ | PC.TType -> "type"
+ | PC.TParameter -> "parameter"
+ | PC.TConstant -> "constant"
+ | PC.TExpression -> "expression"
+ | PC.TIdExpression -> "idexpression"
+ | PC.TStatement -> "statement"
+ | PC.TPosition -> "position"
+ | PC.TPosAny -> "any"
+ | PC.TFunction -> "function"
+ | PC.TLocal -> "local"
+ | PC.Tlist -> "list"
+ | PC.TFresh -> "fresh"
+ | PC.TPure -> "pure"
+ | PC.TContext -> "context"
+ | PC.TTypedef -> "typedef"
+ | PC.TDeclarer -> "declarer"
+ | PC.TIterator -> "iterator"
+ | PC.TName -> "name"
+ | PC.TRuleName str -> "rule_name-"^str
+ | PC.TUsing -> "using"
+ | PC.TPathIsoFile str -> "path_iso_file-"^str
+ | PC.TDisable -> "disable"
+ | PC.TExtends -> "extends"
+ | PC.TDepends -> "depends"
+ | PC.TOn -> "on"
+ | PC.TEver -> "ever"
+ | PC.TNever -> "never"
+ | PC.TExists -> "exists"
+ | PC.TForall -> "forall"
+ | PC.TReverse -> "reverse"
+ | PC.TError -> "error"
+ | PC.TWords -> "words"
+
+ | PC.TNothing -> "nothing"
+
+ | PC.Tchar(clt) -> "char"^(line_type2c clt)
+ | PC.Tshort(clt) -> "short"^(line_type2c clt)
+ | PC.Tint(clt) -> "int"^(line_type2c clt)
+ | PC.Tdouble(clt) -> "double"^(line_type2c clt)
+ | PC.Tfloat(clt) -> "float"^(line_type2c clt)
+ | PC.Tlong(clt) -> "long"^(line_type2c clt)
+ | PC.Tvoid(clt) -> "void"^(line_type2c clt)
+ | PC.Tstruct(clt) -> "struct"^(line_type2c clt)
+ | PC.Tunion(clt) -> "union"^(line_type2c clt)
+ | PC.Tunsigned(clt) -> "unsigned"^(line_type2c clt)
+ | PC.Tsigned(clt) -> "signed"^(line_type2c clt)
+ | PC.Tstatic(clt) -> "static"^(line_type2c clt)
+ | PC.Tinline(clt) -> "inline"^(line_type2c clt)
+ | PC.Ttypedef(clt) -> "typedef"^(line_type2c clt)
+ | PC.Tattr(s,clt) -> s^(line_type2c clt)
+ | PC.Tauto(clt) -> "auto"^(line_type2c clt)
+ | PC.Tregister(clt) -> "register"^(line_type2c clt)
+ | PC.Textern(clt) -> "extern"^(line_type2c clt)
+ | PC.Tconst(clt) -> "const"^(line_type2c clt)
+ | PC.Tvolatile(clt) -> "volatile"^(line_type2c clt)
+
+ | PC.TPragma(s) -> s
+ | PC.TIncludeL(s,clt) -> (pr "#include \"%s\"" s)^(line_type2c clt)
+ | PC.TIncludeNL(s,clt) -> (pr "#include <%s>" s)^(line_type2c clt)
+ | PC.TDefine(clt,_) -> "#define"^(line_type2c clt)
+ | PC.TDefineParam(clt,_,_) -> "#define_param"^(line_type2c clt)
+ | PC.TMinusFile(s,clt) -> (pr "--- %s" s)^(line_type2c clt)
+ | PC.TPlusFile(s,clt) -> (pr "+++ %s" s)^(line_type2c clt)
+
+ | PC.TInc(clt) -> "++"^(line_type2c clt)
+ | PC.TDec(clt) -> "--"^(line_type2c clt)
+
+ | PC.TIf(clt) -> "if"^(line_type2c clt)
+ | PC.TElse(clt) -> "else"^(line_type2c clt)
+ | PC.TWhile(clt) -> "while"^(line_type2c clt)
+ | PC.TFor(clt) -> "for"^(line_type2c clt)
+ | PC.TDo(clt) -> "do"^(line_type2c clt)
+ | PC.TSwitch(clt) -> "switch"^(line_type2c clt)
+ | PC.TCase(clt) -> "case"^(line_type2c clt)
+ | PC.TDefault(clt) -> "default"^(line_type2c clt)
+ | PC.TReturn(clt) -> "return"^(line_type2c clt)
+ | PC.TBreak(clt) -> "break"^(line_type2c clt)
+ | PC.TContinue(clt) -> "continue"^(line_type2c clt)
+ | PC.TGoto(clt) -> "goto"^(line_type2c clt)
+ | PC.TIdent(s,clt) -> (pr "ident-%s" s)^(line_type2c clt)
+ | PC.TTypeId(s,clt) -> (pr "typename-%s" s)^(line_type2c clt)
+ | PC.TDeclarerId(s,clt) -> (pr "declarername-%s" s)^(line_type2c clt)
+ | PC.TIteratorId(s,clt) -> (pr "iteratorname-%s" s)^(line_type2c clt)
+ | PC.TMetaDeclarer(_,_,_,clt) -> "declmeta"^(line_type2c clt)
+ | PC.TMetaIterator(_,_,_,clt) -> "itermeta"^(line_type2c clt)
+
+ | PC.TSizeof(clt) -> "sizeof"^(line_type2c clt)
+
+ | PC.TString(x,clt) -> x^(line_type2c clt)
+ | PC.TChar(x,clt) -> x^(line_type2c clt)
+ | PC.TFloat(x,clt) -> x^(line_type2c clt)
+ | PC.TInt(x,clt) -> x^(line_type2c clt)
+
+ | PC.TOrLog(clt) -> "||"^(line_type2c clt)
+ | PC.TAndLog(clt) -> "&&"^(line_type2c clt)
+ | PC.TOr(clt) -> "|"^(line_type2c clt)
+ | PC.TXor(clt) -> "^"^(line_type2c clt)
+ | PC.TAnd (clt) -> "&"^(line_type2c clt)
+ | PC.TEqEq(clt) -> "=="^(line_type2c clt)
+ | PC.TNotEq(clt) -> "!="^(line_type2c clt)
+ | PC.TLogOp(op,clt) ->
+ (match op with
+ Ast.Inf -> "<"
+ | Ast.InfEq -> "<="
+ | Ast.Sup -> ">"
+ | Ast.SupEq -> ">="
+ | _ -> failwith "not possible")
+ ^(line_type2c clt)
+ | PC.TShOp(op,clt) ->
+ (match op with
+ Ast.DecLeft -> "<<"
+ | Ast.DecRight -> ">>"
+ | _ -> failwith "not possible")
+ ^(line_type2c clt)
+ | PC.TPlus(clt) -> "+"^(line_type2c clt)
+ | PC.TMinus(clt) -> "-"^(line_type2c clt)
+ | PC.TMul(clt) -> "*"^(line_type2c clt)
+ | PC.TDmOp(op,clt) ->
+ (match op with
+ Ast.Div -> "/"
+ | Ast.Mod -> "%"
+ | _ -> failwith "not possible")
+ ^(line_type2c clt)
+ | PC.TTilde (clt) -> "~"^(line_type2c clt)
+
+ | PC.TMetaParam(_,_,clt) -> "parammeta"^(line_type2c clt)
+ | PC.TMetaParamList(_,_,_,clt) -> "paramlistmeta"^(line_type2c clt)
+ | PC.TMetaConst(_,_,_,_,clt) -> "constmeta"^(line_type2c clt)
+ | PC.TMetaErr(_,_,_,clt) -> "errmeta"^(line_type2c clt)
+ | PC.TMetaExp(_,_,_,_,clt) -> "expmeta"^(line_type2c clt)
+ | PC.TMetaIdExp(_,_,_,_,clt) -> "idexpmeta"^(line_type2c clt)
+ | PC.TMetaLocalIdExp(_,_,_,_,clt) -> "localidexpmeta"^(line_type2c clt)
+ | PC.TMetaExpList(_,_,_,clt) -> "explistmeta"^(line_type2c clt)
+ | PC.TMetaId(_,_,_,clt) -> "idmeta"^(line_type2c clt)
+ | PC.TMetaType(_,_,clt) -> "typemeta"^(line_type2c clt)
+ | PC.TMetaStm(_,_,clt) -> "stmmeta"^(line_type2c clt)
+ | PC.TMetaStmList(_,_,clt) -> "stmlistmeta"^(line_type2c clt)
+ | PC.TMetaFunc(_,_,_,clt) -> "funcmeta"^(line_type2c clt)
+ | PC.TMetaLocalFunc(_,_,_,clt) -> "funcmeta"^(line_type2c clt)
+ | PC.TMetaPos(_,_,_,clt) -> "posmeta"
+ | PC.TMPtVirg -> ";"
+ | PC.TArobArob -> "@@"
+ | PC.TArob -> "@"
+ | PC.TPArob -> "P@"
+ | PC.TScript -> "script"
+
+ | PC.TWhen(clt) -> "WHEN"^(line_type2c clt)
+ | PC.TWhenTrue(clt) -> "WHEN TRUE"^(line_type2c clt)
+ | PC.TWhenFalse(clt) -> "WHEN FALSE"^(line_type2c clt)
+ | PC.TAny(clt) -> "ANY"^(line_type2c clt)
+ | PC.TStrict(clt) -> "STRICT"^(line_type2c clt)
+ | PC.TEllipsis(clt) -> "..."^(line_type2c clt)
+(*
+ | PC.TCircles(clt) -> "ooo"^(line_type2c clt)
+ | PC.TStars(clt) -> "***"^(line_type2c clt)
+*)
+
+ | PC.TOEllipsis(clt) -> "<..."^(line_type2c clt)
+ | PC.TCEllipsis(clt) -> "...>"^(line_type2c clt)
+ | PC.TPOEllipsis(clt) -> "<+..."^(line_type2c clt)
+ | PC.TPCEllipsis(clt) -> "...+>"^(line_type2c clt)
+(*
+ | PC.TOCircles(clt) -> "<ooo"^(line_type2c clt)
+ | PC.TCCircles(clt) -> "ooo>"^(line_type2c clt)
+ | PC.TOStars(clt) -> "<***"^(line_type2c clt)
+ | PC.TCStars(clt) -> "***>"^(line_type2c clt)
+*)
+ | PC.TBang0 -> "!"
+ | PC.TPlus0 -> "+"
+ | PC.TWhy0 -> "?"
+
+ | PC.TWhy(clt) -> "?"^(line_type2c clt)
+ | PC.TDotDot(clt) -> ":"^(line_type2c clt)
+ | PC.TBang(clt) -> "!"^(line_type2c clt)
+ | PC.TOPar(clt) -> "("^(line_type2c clt)
+ | PC.TOPar0(clt) -> "("^(line_type2c clt)
+ | PC.TMid0(clt) -> "|"^(line_type2c clt)
+ | PC.TCPar(clt) -> ")"^(line_type2c clt)
+ | PC.TCPar0(clt) -> ")"^(line_type2c clt)
+
+ | PC.TOBrace(clt) -> "{"^(line_type2c clt)
+ | PC.TCBrace(clt) -> "}"^(line_type2c clt)
+ | PC.TOCro(clt) -> "["^(line_type2c clt)
+ | PC.TCCro(clt) -> "]"^(line_type2c clt)
+
+ | PC.TPtrOp(clt) -> "->"^(line_type2c clt)
+
+ | PC.TEq(clt) -> "="^(line_type2c clt)
+ | PC.TAssign(_,clt) -> "=op"^(line_type2c clt)
+ | PC.TDot(clt) -> "."^(line_type2c clt)
+ | PC.TComma(clt) -> ","^(line_type2c clt)
+ | PC.TPtVirg(clt) -> ";"^(line_type2c clt)
+
+ | PC.EOF -> "eof"
+ | PC.TLineEnd(clt) -> "line end"
+ | PC.TInvalid -> "invalid"
+ | PC.TFunDecl(clt) -> "fundecl"
+
+ | PC.TIso -> "<=>"
+ | PC.TRightIso -> "=>"
+ | PC.TIsoTopLevel -> "TopLevel"
+ | PC.TIsoExpression -> "Expression"
+ | PC.TIsoArgExpression -> "ArgExpression"
+ | PC.TIsoTestExpression -> "TestExpression"
+ | PC.TIsoStatement -> "Statement"
+ | PC.TIsoDeclaration -> "Declaration"
+ | PC.TIsoType -> "Type"
+ | PC.TScriptData s -> s
+
+let print_tokens s tokens =
+ Printf.printf "%s\n" s;
+ List.iter (function x -> Printf.printf "%s " (token2c x)) tokens;
+ Printf.printf "\n\n";
+ flush stdout
+
+type plus = PLUS | NOTPLUS | SKIP
+
+let plus_attachable (tok,_) =
+ match tok with
+ PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt) | PC.Tstatic(clt)
+ | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt)
+ | PC.Tauto(clt) | PC.Tregister(clt)
+ | PC.Textern(clt) | PC.Tconst(clt) | PC.Tvolatile(clt)
+
+ | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TDefine(clt,_)
+ | PC.TDefineParam(clt,_,_) | PC.TMinusFile(_,clt) | PC.TPlusFile(_,clt)
+
+ | PC.TInc(clt) | PC.TDec(clt)
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch(clt) | PC.TCase(clt) | PC.TDefault(clt) | PC.TReturn(clt)
+ | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt) | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+
+ | PC.TSizeof(clt)
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt)
+
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaErr(_,_,_,clt)
+ | PC.TMetaExp(_,_,_,_,clt) | PC.TMetaIdExp(_,_,_,_,clt)
+ | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt)
+ | PC.TMetaType(_,_,clt) | PC.TMetaStm(_,_,clt)
+ | PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
+ | PC.TMetaLocalFunc(_,_,_,clt)
+
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
+ | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ (* | PC.TCircles(clt) | PC.TStars(clt) *)
+
+ | PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
+ | PC.TCPar(clt)
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+
+ | PC.TPtrOp(clt)
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt) ->
+ if line_type clt = D.PLUS then PLUS else NOTPLUS
+
+ | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar0(clt)
+ | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+ | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (* | PC.TOCircles(clt)
+ | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *) -> NOTPLUS
+ | PC.TMetaPos(nm,_,_,_) -> NOTPLUS
+
+ | _ -> SKIP
+
+let get_clt (tok,_) =
+ match tok with
+ PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt) | PC.Tstatic(clt)
+ | PC.Tinline(clt) | PC.Tattr(_,clt) | PC.Tauto(clt) | PC.Tregister(clt)
+ | PC.Textern(clt) | PC.Tconst(clt) | PC.Tvolatile(clt)
+
+ | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TDefine(clt,_)
+ | PC.TDefineParam(clt,_,_) | PC.TMinusFile(_,clt) | PC.TPlusFile(_,clt)
+
+ | PC.TInc(clt) | PC.TDec(clt)
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch(clt) | PC.TCase(clt) | PC.TDefault(clt) | PC.TReturn(clt)
+ | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt) | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+
+ | PC.TSizeof(clt)
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt)
+
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaErr(_,_,_,clt)
+ | PC.TMetaExp(_,_,_,_,clt) | PC.TMetaIdExp(_,_,_,_,clt)
+ | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt)
+ | PC.TMetaType(_,_,clt) | PC.TMetaStm(_,_,clt)
+ | PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
+ | PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
+
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt) |
+ PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ (* | PC.TCircles(clt) | PC.TStars(clt) *)
+
+ | PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
+ | PC.TCPar(clt)
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+
+ | PC.TPtrOp(clt)
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt)
+
+ | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar0(clt)
+ | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+ | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (* | PC.TOCircles(clt)
+ | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *) -> clt
+
+ | _ -> failwith "no clt"
+
+let update_clt (tok,x) clt =
+ match tok with
+ PC.Tchar(_) -> (PC.Tchar(clt),x)
+ | PC.Tshort(_) -> (PC.Tshort(clt),x)
+ | PC.Tint(_) -> (PC.Tint(clt),x)
+ | PC.Tdouble(_) -> (PC.Tdouble(clt),x)
+ | PC.Tfloat(_) -> (PC.Tfloat(clt),x)
+ | PC.Tlong(_) -> (PC.Tlong(clt),x)
+ | PC.Tvoid(_) -> (PC.Tvoid(clt),x)
+ | PC.Tstruct(_) -> (PC.Tstruct(clt),x)
+ | PC.Tunion(_) -> (PC.Tunion(clt),x)
+ | PC.Tunsigned(_) -> (PC.Tunsigned(clt),x)
+ | PC.Tsigned(_) -> (PC.Tsigned(clt),x)
+ | PC.Tstatic(_) -> (PC.Tstatic(clt),x)
+ | PC.Tinline(_) -> (PC.Tinline(clt),x)
+ | PC.Ttypedef(_) -> (PC.Ttypedef(clt),x)
+ | PC.Tattr(s,_) -> (PC.Tattr(s,clt),x)
+ | PC.Tauto(_) -> (PC.Tauto(clt),x)
+ | PC.Tregister(_) -> (PC.Tregister(clt),x)
+ | PC.Textern(_) -> (PC.Textern(clt),x)
+ | PC.Tconst(_) -> (PC.Tconst(clt),x)
+ | PC.Tvolatile(_) -> (PC.Tvolatile(clt),x)
+
+ | PC.TIncludeL(s,_) -> (PC.TIncludeL(s,clt),x)
+ | PC.TIncludeNL(s,_) -> (PC.TIncludeNL(s,clt),x)
+ | PC.TDefine(_,a) -> (PC.TDefine(clt,a),x)
+ | PC.TDefineParam(_,a,b) -> (PC.TDefineParam(clt,a,b),x)
+ | PC.TMinusFile(s,_) -> (PC.TMinusFile(s,clt),x)
+ | PC.TPlusFile(s,_) -> (PC.TPlusFile(s,clt),x)
+
+ | PC.TInc(_) -> (PC.TInc(clt),x)
+ | PC.TDec(_) -> (PC.TDec(clt),x)
+
+ | PC.TIf(_) -> (PC.TIf(clt),x)
+ | PC.TElse(_) -> (PC.TElse(clt),x)
+ | PC.TWhile(_) -> (PC.TWhile(clt),x)
+ | PC.TFor(_) -> (PC.TFor(clt),x)
+ | PC.TDo(_) -> (PC.TDo(clt),x)
+ | PC.TSwitch(_) -> (PC.TSwitch(clt),x)
+ | PC.TCase(_) -> (PC.TCase(clt),x)
+ | PC.TDefault(_) -> (PC.TDefault(clt),x)
+ | PC.TReturn(_) -> (PC.TReturn(clt),x)
+ | PC.TBreak(_) -> (PC.TBreak(clt),x)
+ | PC.TContinue(_) -> (PC.TContinue(clt),x)
+ | PC.TGoto(_) -> (PC.TGoto(clt),x)
+ | PC.TIdent(s,_) -> (PC.TIdent(s,clt),x)
+ | PC.TTypeId(s,_) -> (PC.TTypeId(s,clt),x)
+ | PC.TDeclarerId(s,_) -> (PC.TDeclarerId(s,clt),x)
+ | PC.TIteratorId(s,_) -> (PC.TIteratorId(s,clt),x)
+
+ | PC.TSizeof(_) -> (PC.TSizeof(clt),x)
+
+ | PC.TString(s,_) -> (PC.TString(s,clt),x)
+ | PC.TChar(s,_) -> (PC.TChar(s,clt),x)
+ | PC.TFloat(s,_) -> (PC.TFloat(s,clt),x)
+ | PC.TInt(s,_) -> (PC.TInt(s,clt),x)
+
+ | PC.TOrLog(_) -> (PC.TOrLog(clt),x)
+ | PC.TAndLog(_) -> (PC.TAndLog(clt),x)
+ | PC.TOr(_) -> (PC.TOr(clt),x)
+ | PC.TXor(_) -> (PC.TXor(clt),x)
+ | PC.TAnd (_) -> (PC.TAnd (clt),x)
+ | PC.TEqEq(_) -> (PC.TEqEq(clt),x)
+ | PC.TNotEq(_) -> (PC.TNotEq(clt),x)
+ | PC.TLogOp(op,_) -> (PC.TLogOp(op,clt),x)
+ | PC.TShOp(op,_) -> (PC.TShOp(op,clt),x)
+ | PC.TPlus(_) -> (PC.TPlus(clt),x)
+ | PC.TMinus(_) -> (PC.TMinus(clt),x)
+ | PC.TMul(_) -> (PC.TMul(clt),x)
+ | PC.TDmOp(op,_) -> (PC.TDmOp(op,clt),x)
+ | PC.TTilde (_) -> (PC.TTilde (clt),x)
+
+ | PC.TMetaParam(a,b,_) -> (PC.TMetaParam(a,b,clt),x)
+ | PC.TMetaParamList(a,b,c,_) -> (PC.TMetaParamList(a,b,c,clt),x)
+ | PC.TMetaConst(a,b,c,d,_) -> (PC.TMetaConst(a,b,c,d,clt),x)
+ | PC.TMetaErr(a,b,c,_) -> (PC.TMetaErr(a,b,c,clt),x)
+ | PC.TMetaExp(a,b,c,d,_) -> (PC.TMetaExp(a,b,c,d,clt),x)
+ | PC.TMetaIdExp(a,b,c,d,_) -> (PC.TMetaIdExp(a,b,c,d,clt),x)
+ | PC.TMetaLocalIdExp(a,b,c,d,_) -> (PC.TMetaLocalIdExp(a,b,c,d,clt),x)
+ | PC.TMetaExpList(a,b,c,_) -> (PC.TMetaExpList(a,b,c,clt),x)
+ | PC.TMetaId(a,b,c,_) -> (PC.TMetaId(a,b,c,clt),x)
+ | PC.TMetaType(a,b,_) -> (PC.TMetaType(a,b,clt),x)
+ | PC.TMetaStm(a,b,_) -> (PC.TMetaStm(a,b,clt),x)
+ | PC.TMetaStmList(a,b,_) -> (PC.TMetaStmList(a,b,clt),x)
+ | PC.TMetaFunc(a,b,c,_) -> (PC.TMetaFunc(a,b,c,clt),x)
+ | PC.TMetaLocalFunc(a,b,c,_) -> (PC.TMetaLocalFunc(a,b,c,clt),x)
+
+ | PC.TWhen(_) -> (PC.TWhen(clt),x)
+ | PC.TWhenTrue(_) -> (PC.TWhenTrue(clt),x)
+ | PC.TWhenFalse(_) -> (PC.TWhenFalse(clt),x)
+ | PC.TAny(_) -> (PC.TAny(clt),x)
+ | PC.TStrict(_) -> (PC.TStrict(clt),x)
+ | PC.TEllipsis(_) -> (PC.TEllipsis(clt),x)
+(*
+ | PC.TCircles(_) -> (PC.TCircles(clt),x)
+ | PC.TStars(_) -> (PC.TStars(clt),x)
+*)
+
+ | PC.TOEllipsis(_) -> (PC.TOEllipsis(clt),x)
+ | PC.TCEllipsis(_) -> (PC.TCEllipsis(clt),x)
+ | PC.TPOEllipsis(_) -> (PC.TPOEllipsis(clt),x)
+ | PC.TPCEllipsis(_) -> (PC.TPCEllipsis(clt),x)
+(*
+ | PC.TOCircles(_) -> (PC.TOCircles(clt),x)
+ | PC.TCCircles(_) -> (PC.TCCircles(clt),x)
+ | PC.TOStars(_) -> (PC.TOStars(clt),x)
+ | PC.TCStars(_) -> (PC.TCStars(clt),x)
+*)
+
+ | PC.TWhy(_) -> (PC.TWhy(clt),x)
+ | PC.TDotDot(_) -> (PC.TDotDot(clt),x)
+ | PC.TBang(_) -> (PC.TBang(clt),x)
+ | PC.TOPar(_) -> (PC.TOPar(clt),x)
+ | PC.TOPar0(_) -> (PC.TOPar0(clt),x)
+ | PC.TMid0(_) -> (PC.TMid0(clt),x)
+ | PC.TCPar(_) -> (PC.TCPar(clt),x)
+ | PC.TCPar0(_) -> (PC.TCPar0(clt),x)
+
+ | PC.TOBrace(_) -> (PC.TOBrace(clt),x)
+ | PC.TCBrace(_) -> (PC.TCBrace(clt),x)
+ | PC.TOCro(_) -> (PC.TOCro(clt),x)
+ | PC.TCCro(_) -> (PC.TCCro(clt),x)
+
+ | PC.TPtrOp(_) -> (PC.TPtrOp(clt),x)
+
+ | PC.TEq(_) -> (PC.TEq(clt),x)
+ | PC.TAssign(s,_) -> (PC.TAssign(s,clt),x)
+ | PC.TDot(_) -> (PC.TDot(clt),x)
+ | PC.TComma(_) -> (PC.TComma(clt),x)
+ | PC.TPtVirg(_) -> (PC.TPtVirg(clt),x)
+
+ | PC.TLineEnd(_) -> (PC.TLineEnd(clt),x)
+ | PC.TFunDecl(_) -> (PC.TFunDecl(clt),x)
+
+ | _ -> failwith "no clt"
+
+
+(* ----------------------------------------------------------------------- *)
+
+let make_name prefix ln = Printf.sprintf "%s starting on line %d" prefix ln
+
+(* ----------------------------------------------------------------------- *)
+(* Read tokens *)
+
+let wrap_lexbuf_info lexbuf =
+ (Lexing.lexeme lexbuf, Lexing.lexeme_start lexbuf)
+
+let tokens_all_full token table file get_ats lexbuf end_markers :
+ (bool * ((PC.token * (string * (int * int) * (int * int))) list)) =
+ try
+ let rec aux () =
+ let result = token lexbuf in
+ let info = (Lexing.lexeme lexbuf,
+ (table.(Lexing.lexeme_start lexbuf)),
+ (Lexing.lexeme_start lexbuf, Lexing.lexeme_end lexbuf)) in
+ if result = PC.EOF
+ then
+ if get_ats
+ then failwith "unexpected end of file in a metavariable declaration"
+ else (false,[(result,info)])
+ else if List.mem result end_markers
+ then (true,[(result,info)])
+ else
+ let (more,rest) = aux() in
+ (more,(result, info)::rest)
+ in aux ()
+ with
+ e -> pr2 (Common.error_message file (wrap_lexbuf_info lexbuf) ); raise e
+
+let tokens_all table file get_ats lexbuf end_markers :
+ (bool * ((PC.token * (string * (int * int) * (int * int))) list)) =
+ tokens_all_full Lexer_cocci.token table file get_ats lexbuf end_markers
+
+let tokens_script_all table file get_ats lexbuf end_markers :
+ (bool * ((PC.token * (string * (int * int) * (int * int))) list)) =
+ tokens_all_full Lexer_script.token table file get_ats lexbuf end_markers
+
+(* ----------------------------------------------------------------------- *)
+(* Split tokens into minus and plus fragments *)
+
+let split t clt =
+ let (d,_,_,_,_,_,_,_) = clt in
+ match d with
+ D.MINUS | D.OPTMINUS | D.UNIQUEMINUS -> ([t],[])
+ | D.PLUS -> ([],[t])
+ | D.CONTEXT | D.UNIQUE | D.OPT -> ([t],[t])
+
+let split_token ((tok,_) as t) =
+ match tok with
+ PC.TIdentifier | PC.TConstant | PC.TExpression | PC.TIdExpression
+ | PC.TStatement | PC.TPosition | PC.TPosAny
+ | PC.TFunction | PC.TTypedef | PC.TDeclarer | PC.TIterator | PC.TName
+ | PC.TType | PC.TParameter | PC.TLocal | PC.Tlist | PC.TFresh | PC.TPure
+ | PC.TContext | PC.TRuleName(_) | PC.TUsing | PC.TDisable | PC.TExtends
+ | PC.TPathIsoFile(_)
+ | PC.TDepends | PC.TOn | PC.TEver | PC.TNever | PC.TExists | PC.TForall
+ | PC.TReverse
+ | PC.TError | PC.TWords | PC.TNothing -> ([t],[t])
+
+ | PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
+ | PC.Tstatic(clt) | PC.Tauto(clt) | PC.Tregister(clt) | PC.Textern(clt)
+ | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt)
+ | PC.Tconst(clt) | PC.Tvolatile(clt) -> split t clt
+
+ | PC.TPragma(s) -> ([],[t]) (* only allowed in + *)
+ | PC.TPlusFile(s,clt) | PC.TMinusFile(s,clt)
+ | PC.TIncludeL(s,clt) | PC.TIncludeNL(s,clt) ->
+ split t clt
+ | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_) -> split t clt
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch(clt) | PC.TCase(clt) | PC.TDefault(clt)
+ | PC.TSizeof(clt)
+ | PC.TReturn(clt) | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt)
+ | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaExp(_,_,_,_,clt)
+ | PC.TMetaIdExp(_,_,_,_,clt) | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt) | PC.TMetaType(_,_,clt)
+ | PC.TMetaStm(_,_,clt) | PC.TMetaStmList(_,_,clt) | PC.TMetaErr(_,_,_,clt)
+ | PC.TMetaFunc(_,_,_,clt) | PC.TMetaLocalFunc(_,_,_,clt)
+ | PC.TMetaDeclarer(_,_,_,clt) | PC.TMetaIterator(_,_,_,clt) -> split t clt
+ | PC.TMPtVirg | PC.TArob | PC.TArobArob | PC.TScript -> ([t],[t])
+ | PC.TPArob | PC.TMetaPos(_,_,_,_) -> ([t],[])
+
+ | PC.TFunDecl(clt)
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
+ | PC.TAny(clt) | PC.TStrict(clt) | PC.TLineEnd(clt)
+ | PC.TEllipsis(clt) (* | PC.TCircles(clt) | PC.TStars(clt) *) -> split t clt
+
+ | PC.TOEllipsis(_) | PC.TCEllipsis(_) (* clt must be context *)
+ | PC.TPOEllipsis(_) | PC.TPCEllipsis(_) (* clt must be context *)
+(*
+ | PC.TOCircles(_) | PC.TCCircles(_) (* clt must be context *)
+ | PC.TOStars(_) | PC.TCStars(_) (* clt must be context *)
+*)
+ | PC.TBang0 | PC.TPlus0 | PC.TWhy0 ->
+ ([t],[t])
+
+ | PC.TWhy(clt) | PC.TDotDot(clt)
+ | PC.TBang(clt) | PC.TOPar(clt) | PC.TOPar0(clt)
+ | PC.TMid0(clt) | PC.TCPar(clt) | PC.TCPar0(clt) -> split t clt
+
+ | PC.TInc(clt) | PC.TDec(clt) -> split t clt
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt) ->
+ split t clt
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt) -> split t clt
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) -> split t clt
+ | PC.TOCro(clt) | PC.TCCro(clt) -> split t clt
+
+ | PC.TPtrOp(clt) -> split t clt
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt) -> split t clt
+
+ | PC.EOF | PC.TInvalid -> ([t],[t])
+
+ | PC.TIso | PC.TRightIso
+ | PC.TIsoExpression | PC.TIsoStatement | PC.TIsoDeclaration | PC.TIsoType
+ | PC.TIsoTopLevel | PC.TIsoArgExpression | PC.TIsoTestExpression ->
+ failwith "unexpected tokens"
+ | PC.TScriptData s -> ([t],[t])
+
+let split_token_stream tokens =
+ let rec loop = function
+ [] -> ([],[])
+ | token::tokens ->
+ let (minus,plus) = split_token token in
+ let (minus_stream,plus_stream) = loop tokens in
+ (minus@minus_stream,plus@plus_stream) in
+ loop tokens
+
+(* ----------------------------------------------------------------------- *)
+(* Find function names *)
+(* This addresses a shift-reduce problem in the parser, allowing us to
+distinguish a function declaration from a function call even if the latter
+has no return type. Undoubtedly, this is not very nice, but it doesn't
+seem very convenient to refactor the grammar to get around the problem. *)
+
+let rec find_function_names = function
+ [] -> []
+ | ((PC.TIdent(_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
+ | ((PC.TMetaId(_,_,_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
+ | ((PC.TMetaFunc(_,_,_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
+ | ((PC.TMetaLocalFunc(_,_,_,clt),info) as t1)::((PC.TOPar(_),_) as t2)::rest
+ ->
+ let rec skip level = function
+ [] -> ([],false,[])
+ | ((PC.TCPar(_),_) as t)::rest ->
+ let level = level - 1 in
+ if level = 0
+ then ([t],true,rest)
+ else let (pre,found,post) = skip level rest in (t::pre,found,post)
+ | ((PC.TOPar(_),_) as t)::rest ->
+ let level = level + 1 in
+ let (pre,found,post) = skip level rest in (t::pre,found,post)
+ | ((PC.TArobArob,_) as t)::rest
+ | ((PC.TArob,_) as t)::rest
+ | ((PC.EOF,_) as t)::rest -> ([t],false,rest)
+ | t::rest ->
+ let (pre,found,post) = skip level rest in (t::pre,found,post) in
+ let (pre,found,post) = skip 1 rest in
+ (match (found,post) with
+ (true,((PC.TOBrace(_),_) as t3)::rest) ->
+ (PC.TFunDecl(clt),info) :: t1 :: t2 :: pre @
+ t3 :: (find_function_names rest)
+ | _ -> t1 :: t2 :: pre @ find_function_names post)
+ | t :: rest -> t :: find_function_names rest
+
+(* ----------------------------------------------------------------------- *)
+(* an attribute is an identifier that preceeds another identifier and
+ begins with __ *)
+
+let rec detect_attr l =
+ let is_id = function
+ (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
+ | (PC.TMetaLocalFunc(_,_,_,_),_) -> true
+ | _ -> false in
+ let rec loop = function
+ [] -> []
+ | [x] -> [x]
+ | ((PC.TIdent(nm,clt),info) as t1)::id::rest when is_id id ->
+ if String.length nm > 2 && String.sub nm 0 2 = "__"
+ then (PC.Tattr(nm,clt),info)::(loop (id::rest))
+ else t1::(loop (id::rest))
+ | x::xs -> x::(loop xs) in
+ loop l
+
+(* ----------------------------------------------------------------------- *)
+(* Look for variable declarations where the name is a typedef name.
+We assume that C code does not contain a multiplication as a top-level
+statement. *)
+
+(* bug: once a type, always a type, even if the same name is later intended
+ to be used as a real identifier *)
+let detect_types in_meta_decls l =
+ let is_delim infn = function
+ (PC.TOEllipsis(_),_) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
+ | (PC.TPOEllipsis(_),_) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
+ | (PC.TEllipsis(_),_) (* | (PC.TCircles(_),_) | (PC.TStars(_),_) *)
+ | (PC.TPtVirg(_),_) | (PC.TOBrace(_),_) | (PC.TCBrace(_),_)
+ | (PC.TPure,_) | (PC.TContext,_)
+ | (PC.Tstatic(_),_) | (PC.Textern(_),_)
+ | (PC.Tinline(_),_) | (PC.Ttypedef(_),_) | (PC.Tattr(_),_) -> true
+ | (PC.TComma(_),_) when infn > 0 or in_meta_decls -> true
+ | (PC.TDotDot(_),_) when in_meta_decls -> true
+ | _ -> false in
+ let is_choices_delim = function
+ (PC.TOBrace(_),_) | (PC.TComma(_),_) -> true | _ -> false in
+ let is_id = function
+ (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
+ | (PC.TMetaLocalFunc(_,_,_,_),_) -> true
+ | (PC.TMetaParam(_,_,_),_)
+ | (PC.TMetaParamList(_,_,_,_),_)
+ | (PC.TMetaConst(_,_,_,_,_),_)
+ | (PC.TMetaErr(_,_,_,_),_)
+ | (PC.TMetaExp(_,_,_,_,_),_)
+ | (PC.TMetaIdExp(_,_,_,_,_),_)
+ | (PC.TMetaLocalIdExp(_,_,_,_,_),_)
+ | (PC.TMetaExpList(_,_,_,_),_)
+ | (PC.TMetaType(_,_,_),_)
+ | (PC.TMetaStm(_,_,_),_)
+ | (PC.TMetaStmList(_,_,_),_)
+ | (PC.TMetaPos(_,_,_,_),_) -> in_meta_decls
+ | _ -> false in
+ let redo_id ident clt v =
+ !Data.add_type_name ident;
+ (PC.TTypeId(ident,clt),v) in
+ let rec loop start infn type_names = function
+ (* infn: 0 means not in a function header
+ > 0 means in a function header, after infn - 1 unmatched open parens*)
+ [] -> []
+ | ((PC.TOBrace(clt),v)::_) as all when in_meta_decls ->
+ collect_choices type_names all (* never a function header *)
+ | delim::(PC.TIdent(ident,clt),v)::((PC.TMul(_),_) as x)::rest
+ when is_delim infn delim ->
+ let newid = redo_id ident clt v in
+ delim::newid::x::(loop false infn (ident::type_names) rest)
+ | delim::(PC.TIdent(ident,clt),v)::id::rest
+ when is_delim infn delim && is_id id ->
+ let newid = redo_id ident clt v in
+ delim::newid::id::(loop false infn (ident::type_names) rest)
+ | ((PC.TFunDecl(_),_) as fn)::rest ->
+ fn::(loop false 1 type_names rest)
+ | ((PC.TOPar(_),_) as lp)::rest when infn > 0 ->
+ lp::(loop false (infn + 1) type_names rest)
+ | ((PC.TCPar(_),_) as rp)::rest when infn > 0 ->
+ if infn - 1 = 1
+ then rp::(loop false 0 type_names rest) (* 0 means not in fn header *)
+ else rp::(loop false (infn - 1) type_names rest)
+ | (PC.TIdent(ident,clt),v)::((PC.TMul(_),_) as x)::rest when start ->
+ let newid = redo_id ident clt v in
+ newid::x::(loop false infn (ident::type_names) rest)
+ | (PC.TIdent(ident,clt),v)::id::rest when start && is_id id ->
+ let newid = redo_id ident clt v in
+ newid::id::(loop false infn (ident::type_names) rest)
+ | (PC.TIdent(ident,clt),v)::rest when List.mem ident type_names ->
+ (PC.TTypeId(ident,clt),v)::(loop false infn type_names rest)
+ | ((PC.TIdent(ident,clt),v) as x)::rest ->
+ x::(loop false infn type_names rest)
+ | x::rest -> x::(loop false infn type_names rest)
+ and collect_choices type_names = function
+ [] -> [] (* should happen, but let the parser detect that *)
+ | (PC.TCBrace(clt),v)::rest ->
+ (PC.TCBrace(clt),v)::(loop false 0 type_names rest)
+ | delim::(PC.TIdent(ident,clt),v)::rest
+ when is_choices_delim delim ->
+ let newid = redo_id ident clt v in
+ delim::newid::(collect_choices (ident::type_names) rest)
+ | x::rest -> x::(collect_choices type_names rest) in
+ loop true 0 [] l
+
+
+(* ----------------------------------------------------------------------- *)
+(* Insert TLineEnd tokens at the end of a line that contains a WHEN.
+ WHEN is restricted to a single line, to avoid ambiguity in eg:
+ ... WHEN != x
+ +3 *)
+
+let token2line (tok,_) =
+ match tok with
+ PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
+ | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+ | PC.Tunion(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
+ | PC.Tstatic(clt) | PC.Tauto(clt) | PC.Tregister(clt) | PC.Textern(clt)
+ | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt) | PC.Tconst(clt)
+ | PC.Tvolatile(clt)
+
+ | PC.TInc(clt) | PC.TDec(clt)
+
+ | PC.TIf(clt) | PC.TElse(clt) | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
+ | PC.TSwitch (clt) | PC.TCase (clt) | PC.TDefault (clt) | PC.TSizeof (clt)
+ | PC.TReturn(clt) | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt)
+ | PC.TIdent(_,clt)
+ | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
+ | PC.TMetaDeclarer(_,_,_,clt) | PC.TMetaIterator(_,_,_,clt)
+
+ | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
+
+ | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
+ | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
+ | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+ | PC.TDmOp(_,clt) | PC.TTilde (clt)
+
+ | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+ | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaExp(_,_,_,_,clt)
+ | PC.TMetaIdExp(_,_,_,_,clt) | PC.TMetaLocalIdExp(_,_,_,_,clt)
+ | PC.TMetaExpList(_,_,_,clt)
+ | PC.TMetaId(_,_,_,clt) | PC.TMetaType(_,_,clt)
+ | PC.TMetaStm(_,_,clt) | PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
+ | PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
+
+ | PC.TFunDecl(clt)
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
+ | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ (* | PC.TCircles(clt) | PC.TStars(clt) *)
+
+ | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+ | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (*| PC.TOCircles(clt)
+ | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *)
+
+ | PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
+ | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar(clt)
+ | PC.TCPar0(clt)
+
+ | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+
+ | PC.TPtrOp(clt)
+
+ | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_)
+ | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt)
+
+ | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
+ | PC.TPtVirg(clt) ->
+ let (_,line,_,_,_,_,_,_) = clt in Some line
+
+ | _ -> None
+
+let rec insert_line_end = function
+ [] -> []
+ | (((PC.TWhen(clt),q) as x)::xs) ->
+ x::(find_line_end true (token2line x) clt q xs)
+ | (((PC.TDefine(clt,_),q) as x)::xs)
+ | (((PC.TDefineParam(clt,_,_),q) as x)::xs) ->
+ x::(find_line_end false (token2line x) clt q xs)
+ | x::xs -> x::(insert_line_end xs)
+
+and find_line_end inwhen line clt q = function
+ (* don't know what 2nd component should be so just use the info of
+ the When. Also inherit - of when, if any *)
+ [] -> [(PC.TLineEnd(clt),q)]
+ | ((PC.TIdent("strict",clt),a) as x)::xs when token2line x = line ->
+ (PC.TStrict(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("STRICT",clt),a) as x)::xs when token2line x = line ->
+ (PC.TStrict(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("any",clt),a) as x)::xs when token2line x = line ->
+ (PC.TAny(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("ANY",clt),a) as x)::xs when token2line x = line ->
+ (PC.TAny(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("forall",clt),a) as x)::xs when token2line x = line ->
+ (PC.TForall,a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TIdent("exists",clt),a) as x)::xs when token2line x = line ->
+ (PC.TExists,a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TComma(clt),a) as x)::xs when token2line x = line ->
+ (PC.TComma(clt),a) :: (find_line_end inwhen line clt q xs)
+ | ((PC.TPArob,a) as x)::xs -> (* no line #, just assume on the same line *)
+ x :: (find_line_end inwhen line clt q xs)
+ | x::xs when token2line x = line -> x :: (find_line_end inwhen line clt q xs)
+ | xs -> (PC.TLineEnd(clt),q)::(insert_line_end xs)
+
+let rec translate_when_true_false = function
+ [] -> []
+ | (PC.TWhen(clt),q)::((PC.TNotEq(_),_) as x)::(PC.TIdent("true",_),_)::xs ->
+ (PC.TWhenTrue(clt),q)::x::xs
+ | (PC.TWhen(clt),q)::((PC.TNotEq(_),_) as x)::(PC.TIdent("false",_),_)::xs ->
+ (PC.TWhenFalse(clt),q)::x::xs
+ | x::xs -> x :: (translate_when_true_false xs)
+
+(* ----------------------------------------------------------------------- *)
+(* process pragmas: they can only be used in + code, and adjacent to
+another + token. They are concatenated to the string representation of
+that other token. *)
+
+let rec collect_all_pragmas collected = function
+ (PC.TPragma(s),_)::rest -> collect_all_pragmas (s::collected) rest
+ | l -> (List.rev collected,l)
+
+let rec collect_up_to_pragmas skipped = function
+ [] -> None (* didn't reach a pragma, so nothing to do *)
+ | ((PC.TPragma(s),_) as t)::rest ->
+ let (pragmas,rest) = collect_all_pragmas [] (t::rest) in
+ Some (List.rev skipped,pragmas,rest)
+ | x::xs ->
+ match plus_attachable x with
+ PLUS -> None
+ | NOTPLUS -> None
+ | SKIP -> collect_up_to_pragmas (x::skipped) xs
+
+let rec collect_up_to_plus skipped = function
+ [] -> failwith "nothing to attach a pragma to"
+ | x::xs ->
+ match plus_attachable x with
+ PLUS -> (List.rev skipped,x,xs)
+ | NOTPLUS -> failwith "nothing to attach a pragma to"
+ | SKIP -> collect_up_to_plus (x::skipped) xs
+
+let rec process_pragmas = function
+ [] -> []
+ | ((PC.TPragma(s),_)::_) as l ->
+ let (pragmas,rest) = collect_all_pragmas [] l in
+ let (skipped,aft,rest) = collect_up_to_plus [] rest in
+ let (a,b,c,d,e,strbef,straft,pos) = get_clt aft in
+ skipped@
+ (process_pragmas ((update_clt aft (a,b,c,d,e,pragmas,straft,pos))::rest))
+ | bef::xs ->
+ (match plus_attachable bef with
+ PLUS ->
+ (match collect_up_to_pragmas [] xs with
+ Some(skipped,pragmas,rest) ->
+ let (a,b,c,d,e,strbef,straft,pos) = get_clt bef in
+ (update_clt bef (a,b,c,d,e,strbef,pragmas,pos))::
+ skipped@(process_pragmas rest)
+ | None -> bef::(process_pragmas xs))
+ | _ -> bef::(process_pragmas xs))
+
+(* ----------------------------------------------------------------------- *)
+(* Drop ... ... . This is only allowed in + code, and arises when there is
+some - code between the ... *)
+(* drop whens as well - they serve no purpose in + code and they cause
+problems for drop_double_dots *)
+
+let rec drop_when = function
+ [] -> []
+ | (PC.TWhen(clt),info)::xs ->
+ let rec loop = function
+ [] -> []
+ | (PC.TLineEnd(_),info)::xs -> drop_when xs
+ | x::xs -> loop xs in
+ loop xs
+ | x::xs -> x::drop_when xs
+
+(* instead of dropping the double dots, we put TNothing in between them.
+these vanish after the parser, but keeping all the ...s in the + code makes
+it easier to align the + and - code in context_neg and in preparation for the
+isomorphisms. This shouldn't matter because the context code of the +
+slice is mostly ignored anyway *)
+let rec drop_double_dots l =
+ let start = function
+ (PC.TOEllipsis(_),_) | (PC.TPOEllipsis(_),_)
+ (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *) ->
+ true
+ | _ -> false in
+ let middle = function
+ (PC.TEllipsis(_),_) (* | (PC.TCircles(_),_) | (PC.TStars(_),_) *) -> true
+ | _ -> false in
+ let final = function
+ (PC.TCEllipsis(_),_) | (PC.TPCEllipsis(_),_)
+ (* | (PC.TCCircles(_),_) | (PC.TCStars(_),_) *) ->
+ true
+ | _ -> false in
+ let rec loop ((_,i) as prev) = function
+ [] -> []
+ | x::rest when middle prev && middle x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest when start prev && middle x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest when start prev && final x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest when middle prev && final x -> (PC.TNothing,i)::x::(loop x rest)
+ | x::rest -> x :: (loop x rest) in
+ match l with
+ [] -> []
+ | (x::xs) -> x :: loop x xs
+
+let rec fix f l =
+ let cur = f l in
+ if l = cur then l else fix f cur
+
+(* ( | ... | ) also causes parsing problems *)
+
+exception Not_empty
+
+let rec drop_empty_thing starter middle ender = function
+ [] -> []
+ | hd::rest when starter hd ->
+ let rec loop = function
+ x::rest when middle x -> loop rest
+ | x::rest when ender x -> rest
+ | _ -> raise Not_empty in
+ (match try Some(loop rest) with Not_empty -> None with
+ Some x -> drop_empty_thing starter middle ender x
+ | None -> hd :: drop_empty_thing starter middle ender rest)
+ | x::rest -> x :: drop_empty_thing starter middle ender rest
+
+let drop_empty_or =
+ drop_empty_thing
+ (function (PC.TOPar0(_),_) -> true | _ -> false)
+ (function (PC.TMid0(_),_) -> true | _ -> false)
+ (function (PC.TCPar0(_),_) -> true | _ -> false)
+
+let drop_empty_nest = drop_empty_thing
+
+(* ----------------------------------------------------------------------- *)
+(* Read tokens *)
+
+let get_s_starts (_, (s,_,(starts, ends))) =
+ Printf.printf "%d %d\n" starts ends; (s, starts)
+
+let pop2 l =
+ let v = List.hd !l in
+ l := List.tl !l;
+ v
+
+let reinit _ =
+ PC.reinit (function _ -> PC.TArobArob (* a handy token *))
+ (Lexing.from_function
+ (function buf -> function n -> raise Common.Impossible))
+
+let parse_one str parsefn file toks =
+ let all_tokens = ref toks in
+ let cur_tok = ref (List.hd !all_tokens) in
+
+ let lexer_function _ =
+ let (v, info) = pop2 all_tokens in
+ cur_tok := (v, info);
+ v in
+
+ let lexbuf_fake =
+ Lexing.from_function
+ (function buf -> function n -> raise Common.Impossible)
+ in
+
+ reinit();
+
+ try parsefn lexer_function lexbuf_fake
+ with
+ Lexer_cocci.Lexical s ->
+ failwith
+ (Printf.sprintf "%s: lexical error: %s\n =%s\n" str s
+ (Common.error_message file (get_s_starts !cur_tok) ))
+ | Parser_cocci_menhir.Error ->
+ failwith
+ (Printf.sprintf "%s: parse error: \n = %s\n" str
+ (Common.error_message file (get_s_starts !cur_tok) ))
+ | Semantic_cocci.Semantic s ->
+ failwith
+ (Printf.sprintf "%s: semantic error: %s\n =%s\n" str s
+ (Common.error_message file (get_s_starts !cur_tok) ))
+
+ | e -> raise e
+
+let prepare_tokens tokens =
+ translate_when_true_false (* after insert_line_end *)
+ (insert_line_end
+ (detect_types false (find_function_names (detect_attr tokens))))
+
+let rec consume_minus_positions = function
+ [] -> []
+ | x::(PC.TPArob,_)::(PC.TMetaPos(name,constraints,per,clt),_)::xs ->
+ let (arity,ln,lln,offset,col,strbef,straft,_) = get_clt x in
+ let name = Parse_aux.clt2mcode name clt in
+ let x =
+ update_clt x
+ (arity,ln,lln,offset,col,strbef,straft,
+ Ast0.MetaPos(name,constraints,per)) in
+ x::(consume_minus_positions xs)
+ | x::xs -> x::consume_minus_positions xs
+
+let any_modif rule =
+ let mcode x =
+ match Ast0.get_mcode_mcodekind x with
+ Ast0.MINUS _ | Ast0.PLUS -> true
+ | _ -> false in
+ let donothing r k e = k e in
+ let bind x y = x or y in
+ let option_default = false in
+ let fn =
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing donothing donothing
+ donothing donothing in
+ List.exists fn.V0.combiner_top_level rule
+
+let drop_last extra l = List.rev(extra@(List.tl(List.rev l)))
+
+let partition_either l =
+ let rec part_either left right = function
+ | [] -> (List.rev left, List.rev right)
+ | x :: l ->
+ (match x with
+ | Common.Left e -> part_either (e :: left) right l
+ | Common.Right e -> part_either left (e :: right) l) in
+ part_either [] [] l
+
+let get_metavars parse_fn table file lexbuf =
+ let rec meta_loop acc (* read one decl at a time *) =
+ let (_,tokens) =
+ tokens_all table file true lexbuf [PC.TArobArob;PC.TMPtVirg] in
+ let tokens = prepare_tokens tokens in
+ match tokens with
+ [(PC.TArobArob,_)] -> List.rev acc
+ | _ ->
+ let metavars = parse_one "meta" parse_fn file tokens in
+ meta_loop (metavars@acc) in
+ partition_either (meta_loop [])
+
+let get_script_metavars parse_fn table file lexbuf =
+ let rec meta_loop acc =
+ let (_, tokens) =
+ tokens_all table file true lexbuf [PC.TArobArob; PC.TMPtVirg] in
+ let tokens = prepare_tokens tokens in
+ match tokens with
+ [(PC.TArobArob, _)] -> List.rev acc
+ | _ ->
+ let metavar = parse_one "scriptmeta" parse_fn file tokens in
+ meta_loop (metavar :: acc)
+ in
+ meta_loop []
+
+let get_rule_name parse_fn starts_with_name get_tokens file prefix =
+ Data.in_rule_name := true;
+ let mknm _ = make_name prefix (!Lexer_cocci.line) in
+ let name_res =
+ if starts_with_name
+ then
+ let (_,tokens) = get_tokens [PC.TArob] in
+ match parse_one "rule name" parse_fn file tokens with
+ Ast.CocciRulename (None,a,b,c,d,e) ->
+ Ast.CocciRulename (Some (mknm()),a,b,c,d,e)
+ | Ast.CocciRulename (Some nm,a,b,c,d,e) ->
+ (if List.mem nm reserved_names
+ then failwith (Printf.sprintf "invalid name %s\n" nm));
+ Ast.CocciRulename (Some nm,a,b,c,d,e)
+ | Ast.ScriptRulename(s,deps) -> Ast.ScriptRulename(s,deps)
+ else
+ Ast.CocciRulename(Some(mknm()),Ast.NoDep,[],[],Ast.Undetermined,false) in
+ Data.in_rule_name := false;
+ name_res
+
+let parse_iso file =
+ let table = Common.full_charpos_to_pos file in
+ Common.with_open_infile file (fun channel ->
+ let lexbuf = Lexing.from_channel channel in
+ let get_tokens = tokens_all table file false lexbuf in
+ let res =
+ match get_tokens [PC.TArobArob;PC.TArob] with
+ (true,start) ->
+ let parse_start start =
+ let rev = List.rev start in
+ let (arob,_) = List.hd rev in
+ (arob = PC.TArob,List.rev(List.tl rev)) in
+ let (starts_with_name,start) = parse_start start in
+ let rec loop starts_with_name start =
+ (!Data.init_rule)();
+ (* get metavariable declarations - have to be read before the
+ rest *)
+ let (rule_name,_,_,_,_,_) =
+ match get_rule_name PC.iso_rule_name starts_with_name get_tokens
+ file ("iso file "^file) with
+ Ast.CocciRulename (Some n,a,b,c,d,e) -> (n,a,b,c,d,e)
+ | _ -> failwith "Script rules cannot appear in isomorphism rules"
+ in
+ Ast0.rule_name := rule_name;
+ Data.in_meta := true;
+ let iso_metavars =
+ match get_metavars PC.iso_meta_main table file lexbuf with
+ (iso_metavars,[]) -> iso_metavars
+ | _ -> failwith "unexpected inheritance in iso" in
+ Data.in_meta := false;
+ (* get the rule *)
+ let (more,tokens) =
+ get_tokens
+ [PC.TIsoStatement;PC.TIsoExpression;PC.TIsoArgExpression;
+ PC.TIsoTestExpression;
+ PC.TIsoDeclaration;PC.TIsoType;PC.TIsoTopLevel] in
+ let next_start = List.hd(List.rev tokens) in
+ let dummy_info = ("",(-1,-1),(-1,-1)) in
+ let tokens = drop_last [(PC.EOF,dummy_info)] tokens in
+ let tokens = prepare_tokens (start@tokens) in
+ (*
+ print_tokens "iso tokens" tokens;
+ *)
+ let entry = parse_one "iso main" PC.iso_main file tokens in
+ let entry = List.map (List.map Test_exps.process_anything) entry in
+ if more
+ then (* The code below allows a header like Statement list,
+ which is more than one word. We don't have that any more,
+ but the code is left here in case it is put back. *)
+ match get_tokens [PC.TArobArob;PC.TArob] with
+ (true,start) ->
+ let (starts_with_name,start) = parse_start start in
+ (iso_metavars,entry,rule_name) ::
+ (loop starts_with_name (next_start::start))
+ | _ -> failwith "isomorphism ends early"
+ else [(iso_metavars,entry,rule_name)] in
+ loop starts_with_name start
+ | (false,_) -> [] in
+ res)
+
+let parse_iso_files existing_isos iso_files extra_path =
+ let get_names = List.map (function (_,_,nm) -> nm) in
+ let old_names = get_names existing_isos in
+ Data.in_iso := true;
+ let (res,_) =
+ List.fold_left
+ (function (prev,names) ->
+ function file ->
+ Lexer_cocci.init ();
+ let file =
+ match file with
+ Common.Left(fl) -> Filename.concat extra_path fl
+ | Common.Right(fl) -> Filename.concat Config.path fl in
+ let current = parse_iso file in
+ let new_names = get_names current in
+ if List.exists (function x -> List.mem x names) new_names
+ then failwith (Printf.sprintf "repeated iso name found in %s" file);
+ (current::prev,new_names @ names))
+ ([],old_names) iso_files in
+ Data.in_iso := false;
+ existing_isos@(List.concat (List.rev res))
+
+let parse file =
+ let table = Common.full_charpos_to_pos file in
+ Common.with_open_infile file (fun channel ->
+ let lexbuf = Lexing.from_channel channel in
+ let get_tokens = tokens_all table file false lexbuf in
+ Data.in_prolog := true;
+ let initial_tokens = get_tokens [PC.TArobArob;PC.TArob] in
+ Data.in_prolog := false;
+ let res =
+ match initial_tokens with
+ (true,data) ->
+ (match List.rev data with
+ ((PC.TArobArob as x),_)::_ | ((PC.TArob as x),_)::_ ->
+ let iso_files =
+ parse_one "iso file names" PC.include_main file data in
+
+ let parse_cocci_rule old_metas
+ (rule_name, dependencies, iso, dropiso, exists, is_expression) =
+ Ast0.rule_name := rule_name;
+ Data.inheritable_positions :=
+ rule_name :: !Data.inheritable_positions;
+
+ (* get metavariable declarations *)
+ Data.in_meta := true;
+ let (metavars, inherited_metavars) =
+ get_metavars PC.meta_main table file lexbuf in
+ Data.in_meta := false;
+ Hashtbl.add Data.all_metadecls rule_name metavars;
+ Hashtbl.add Lexer_cocci.rule_names rule_name ();
+ Hashtbl.add Lexer_cocci.all_metavariables rule_name
+ (Hashtbl.fold
+ (fun key v rest -> (key,v)::rest)
+ Lexer_cocci.metavariables []);
+
+ (* get transformation rules *)
+ let (more, tokens) = get_tokens [PC.TArobArob; PC.TArob] in
+ let (minus_tokens, plus_tokens) = split_token_stream tokens in
+
+ let minus_tokens = consume_minus_positions minus_tokens in
+ let minus_tokens = prepare_tokens minus_tokens in
+ let plus_tokens = prepare_tokens plus_tokens in
+
+ (*
+ print_tokens "minus tokens" minus_tokens;
+ print_tokens "plus tokens" plus_tokens;
+ *)
+
+ let plus_tokens =
+ process_pragmas
+ (fix (function x -> drop_double_dots (drop_empty_or x))
+ (drop_when plus_tokens)) in
+ (*
+ print_tokens "plus tokens" plus_tokens;
+ Printf.printf "before minus parse\n";
+ *)
+ let minus_res =
+ if is_expression
+ then parse_one "minus" PC.minus_exp_main file minus_tokens
+ else parse_one "minus" PC.minus_main file minus_tokens in
+ (*
+ Unparse_ast0.unparse minus_res;
+ Printf.printf "before plus parse\n";
+ *)
+ let plus_res =
+ if !Flag.sgrep_mode2
+ then (* not actually used for anything, except context_neg *)
+ List.map
+ (Iso_pattern.rebuild_mcode None).V0.rebuilder_top_level
+ minus_res
+ else
+ if is_expression
+ then parse_one "plus" PC.plus_exp_main file plus_tokens
+ else parse_one "plus" PC.plus_main file plus_tokens in
+ (*
+ Printf.printf "after plus parse\n";
+ *)
+
+ (if not !Flag.sgrep_mode2 &&
+ (any_modif minus_res or any_modif plus_res)
+ then Data.inheritable_positions := []);
+
+ Check_meta.check_meta rule_name old_metas inherited_metavars
+ metavars minus_res plus_res;
+
+ (more, Ast0.CocciRule ((minus_res, metavars,
+ (iso, dropiso, dependencies, rule_name, exists)),
+ (plus_res, metavars)), metavars, tokens) in
+
+ let parse_script_rule language old_metas deps =
+ let get_tokens = tokens_script_all table file false lexbuf in
+
+ (* meta-variables *)
+ Data.in_meta := true;
+ let metavars =
+ get_script_metavars PC.script_meta_main table file lexbuf in
+ Data.in_meta := false;
+
+ let exists_in old_metas (py,(r,m)) =
+ let test (rr,mr) x =
+ let (ro,vo) = Ast.get_meta_name x in
+ ro = rr && vo = mr in
+ List.exists (test (r,m)) old_metas in
+
+ List.iter
+ (function x ->
+ let meta2c (r,n) = Printf.sprintf "%s.%s" r n in
+ if not (exists_in old_metas x) then
+ failwith
+ (Printf.sprintf
+ "Script references unknown meta-variable: %s"
+ (meta2c(snd x))))
+ metavars;
+
+ (* script code *)
+ let (more, tokens) = get_tokens [PC.TArobArob; PC.TArob] in
+ let data =
+ match List.hd tokens with
+ (PC.TScriptData(s),_) -> s
+ | (PC.TArobArob,_) | (PC.TArob,_) -> ""
+ | _ -> failwith "Malformed script rule" in
+ (more,Ast0.ScriptRule(language, deps, metavars, data),[],tokens) in
+
+ let parse_rule old_metas starts_with_name =
+ let rulename =
+ get_rule_name PC.rule_name starts_with_name get_tokens file
+ "rule" in
+ match rulename with
+ Ast.CocciRulename (Some s, a, b, c, d, e) ->
+ parse_cocci_rule old_metas (s, a, b, c, d, e)
+ | Ast.ScriptRulename (l,deps) -> parse_script_rule l old_metas deps
+ | _ -> failwith "Malformed rule name"
+ in
+
+ let rec loop old_metas starts_with_name =
+ (!Data.init_rule)();
+
+ let gen_starts_with_name more tokens =
+ more &&
+ (match List.hd (List.rev tokens) with
+ (PC.TArobArob,_) -> false
+ | (PC.TArob,_) -> true
+ | _ -> failwith "unexpected token")
+ in
+
+ let (more, rule, metavars, tokens) =
+ parse_rule old_metas starts_with_name in
+ if more then
+ rule::
+ (loop (metavars @ old_metas) (gen_starts_with_name more tokens))
+ else [rule];
+
+ in
+
+ (iso_files, loop [] (x = PC.TArob))
+ | _ -> failwith "unexpected code before the first rule\n")
+ | (false,[(PC.TArobArob,_)]) | (false,[(PC.TArob,_)]) ->
+ ([],([] : Ast0.parsed_rule list))
+ | _ -> failwith "unexpected code before the first rule\n" in
+ res)
+
+(* parse to ast0 and then convert to ast *)
+let process file isofile verbose =
+ let extra_path = Filename.dirname file in
+ Lexer_cocci.init();
+ let (iso_files, rules) = parse file in
+ let std_isos =
+ match isofile with
+ None -> []
+ | Some iso_file -> parse_iso_files [] [Common.Left iso_file] "" in
+ let global_isos = parse_iso_files std_isos iso_files extra_path in
+ let rules = Unitary_ast0.do_unitary rules in
+ let parsed =
+ List.map
+ (function
+ Ast0.ScriptRule (a,b,c,d) -> [([],Ast.ScriptRule (a,b,c,d))]
+ | Ast0.CocciRule
+ ((minus, metavarsm,
+ (iso, dropiso, dependencies, rule_name, exists)),
+ (plus, metavars)) ->
+ let chosen_isos =
+ parse_iso_files global_isos
+ (List.map (function x -> Common.Left x) iso)
+ extra_path in
+ let chosen_isos =
+ (* check that dropped isos are actually available *)
+ (try
+ let iso_names =
+ List.map (function (_,_,nm) -> nm) chosen_isos in
+ let local_iso_names = reserved_names @ iso_names in
+ let bad_dropped =
+ List.find
+ (function dropped ->
+ not (List.mem dropped local_iso_names))
+ dropiso in
+ failwith
+ ("invalid iso name " ^ bad_dropped ^ " in " ^ rule_name)
+ with Not_found -> ());
+ if List.mem "all" dropiso
+ then
+ if List.length dropiso = 1
+ then []
+ else failwith "disable all should only be by itself"
+ else (* drop those isos *)
+ List.filter
+ (function (_,_,nm) -> not (List.mem nm dropiso))
+ chosen_isos in
+ List.iter Iso_compile.process chosen_isos;
+ let dropped_isos =
+ match reserved_names with
+ "all"::others ->
+ (match dropiso with
+ ["all"] -> others
+ | _ ->
+ List.filter (function x -> List.mem x dropiso) others)
+ | _ ->
+ failwith
+ "bad list of reserved names - all must be at start" in
+ let minus = Test_exps.process minus in
+ let minus = Compute_lines.compute_lines minus in
+ let plus = Compute_lines.compute_lines plus in
+ let is_exp =
+ (* only relevant to Flag.make_hrule *)
+ (* doesn't handle multiple minirules properly, but since
+ we don't really handle them in lots of other ways, it
+ doesn't seem very important *)
+ match plus with
+ [] -> [false]
+ | p::_ ->
+ [match Ast0.unwrap p with
+ Ast0.CODE c ->
+ (match List.map Ast0.unwrap (Ast0.undots c) with
+ [Ast0.Exp e] -> true | _ -> false)
+ | _ -> false] in
+ let minus = Arity.minus_arity minus in
+ let ((metavars,minus),function_prototypes) =
+ Function_prototypes.process
+ rule_name metavars dropped_isos minus plus in
+ (* warning! context_neg side-effects its arguments *)
+ let (m,p) = List.split (Context_neg.context_neg minus plus) in
+ Type_infer.type_infer p;
+ (if not !Flag.sgrep_mode2 then Insert_plus.insert_plus m p);
+ Type_infer.type_infer minus;
+ let (extra_meta, minus) =
+ Iso_pattern.apply_isos chosen_isos minus rule_name in
+ let minus = Comm_assoc.comm_assoc minus rule_name dropiso in
+ let minus =
+ if !Flag.sgrep_mode2 then minus
+ else Single_statement.single_statement minus in
+ let minus = Simple_assignments.simple_assignments minus in
+ let minus_ast =
+ Ast0toast.ast0toast rule_name dependencies dropped_isos
+ exists minus is_exp in
+ match function_prototypes with
+ None -> [(extra_meta @ metavars, minus_ast)]
+ | Some mv_fp ->
+ [(extra_meta @ metavars, minus_ast); mv_fp])
+(* Ast0.CocciRule ((minus, metavarsm, (iso, dropiso, dependencies, rule_name, exists)), (plus, metavars))*)
+ rules in
+ let parsed = List.concat parsed in
+ let disjd = Disjdistr.disj parsed in
+
+ let (code,fvs,neg_pos,ua,pos) = Free_vars.free_vars disjd in
+ if !Flag_parsing_cocci.show_SP
+ then List.iter Pretty_print_cocci.unparse code;
+
+ let grep_tokens =
+ Common.profile_code "get_constants"
+ (fun () -> Get_constants.get_constants code) in (* for grep *)
+ let glimpse_tokens2 =
+ Common.profile_code "get_glimpse_constants"
+ (fun () -> Get_constants2.get_constants code neg_pos) in(* for glimpse *)
+ (code,fvs,neg_pos,ua,pos,grep_tokens,glimpse_tokens2)
--- /dev/null
+/*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*/
+
+
+%{
+
+(* Not clear how to allow function declarations to specify a return type
+and how to allow both to be specified as static, because they are in
+different rules. The rules seem to have to be combined, which would allow
+functions to be declared as local variables *)
+
+(* Not clear how to let a function have a parameter of type void. At the
+moment, void is allowed to be the type of a variable, which is wrong, and a
+parameter needs both a type and an identifier *)
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module P = Parse_aux
+%}
+
+%token EOF
+
+%token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
+%token TIdExpression
+%token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
+%token TPure TContext
+%token TTypedef TDeclarer TIterator TName TPosition TPosAny
+%token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
+%token TReverse TNothing
+%token<string> TRuleName
+
+%token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
+%token<Data.clt> Tvoid Tstruct Tunion
+%token<Data.clt> Tunsigned Tsigned
+
+%token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
+%token<Data.clt> Tconst Tvolatile
+%token<string * Data.clt> Tattr
+
+%token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
+%token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
+%token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
+
+%token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
+%token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
+%token <Parse_aux.expinfo> TMetaErr
+%token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
+%token <Parse_aux.list_info> TMetaParamList TMetaExpList
+%token <Parse_aux.typed_info> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
+%token <Parse_aux.pos_info> TMetaPos
+
+%token TArob TArobArob TPArob
+%token <string> TScriptData
+
+%token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
+%token <Data.clt> TWhen TAny TStrict TLineEnd
+
+%token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
+%token <Data.clt> TMid0 TCPar TCPar0
+
+%token <string> TPragma TPathIsoFile
+%token <string * Data.clt> TIncludeL TIncludeNL
+%token <Data.clt * token> TDefine
+%token <Data.clt * token * int> TDefineParam
+%token <string * Data.clt> TMinusFile TPlusFile
+
+%token <Data.clt> TInc TDec
+
+%token <string * Data.clt> TString TChar TFloat TInt
+
+%token <Data.clt> TOrLog
+%token <Data.clt> TAndLog
+%token <Data.clt> TOr
+%token <Data.clt> TXor
+%token <Data.clt> TAnd
+%token <Data.clt> TEqEq TNotEq
+%token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
+%token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
+%token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
+%token <Data.clt> TPlus TMinus
+%token <Data.clt> TMul TTilde
+
+%token <Data.clt> TOBrace TCBrace
+%token <Data.clt> TOCro TCCro
+
+%token <Data.clt> TPtrOp
+
+%token TMPtVirg
+%token <Data.clt> TEq TDot TComma TPtVirg
+%token <Ast_cocci.assignOp * Data.clt> TAssign
+
+%token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
+%token TIsoTopLevel TIsoArgExpression TIsoTestExpression
+
+%token TInvalid
+
+/* operator precedence */
+%nonassoc TIf
+%nonassoc TElse
+
+%left TOrLog
+%left TAndLog
+%left TOr
+%left TXor
+%left TAnd
+%left TEqEq TNotEq
+%left TLogOp /* TInf TSup TInfEq TSupEq */
+%left TShOp /* TShl TShr */
+%left TPlus TMinus
+%left TMul TDmOp /* TDiv TMod */
+
+%start reinit
+%type <unit> reinit
+
+%start minus_main
+%type <Ast0_cocci.rule> minus_main
+
+%start minus_exp_main
+%type <Ast0_cocci.rule> minus_exp_main
+
+%start plus_main
+%type <Ast0_cocci.rule> plus_main
+
+%start plus_exp_main
+%type <Ast0_cocci.rule> plus_exp_main
+
+%start include_main
+%type <(string,string) Common.either list> include_main
+
+%start iso_rule_name
+%type <Ast_cocci.rulename>
+iso_rule_name
+
+%start rule_name
+%type <Ast_cocci.rulename>
+rule_name
+
+%start meta_main
+%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
+
+%start <string * (string * string)> script_meta_main
+
+%start iso_main
+%type <Ast0_cocci.anything list list> iso_main
+
+%start iso_meta_main
+%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
+
+%start never_used
+%type <unit> never_used
+
+%%
+
+reinit: { }
+minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
+| m=minus_body TArob { m }
+plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
+| p=plus_body TArob { p }
+minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
+| m=minus_exp_body TArob { m }
+plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
+| p=plus_exp_body TArob { p }
+meta_main: m=metadec { m (!Ast0.rule_name) }
+iso_meta_main: m=metadec { m "" }
+
+/*****************************************************************************
+*
+*
+*****************************************************************************/
+
+pure:
+ TPure { Ast0.Pure }
+| TContext { Ast0.Context }
+| TPure TContext { Ast0.PureContext }
+| TContext TPure { Ast0.PureContext }
+| /* empty */ { Ast0.Impure }
+
+iso_rule_name:
+ nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
+
+rule_name:
+ nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
+ a=loption(disable) e=exists ee=is_expression TArob
+ { P.make_cocci_rule_name_result nm d i a e ee }
+ | scr=pure_ident TDotDot lang=pure_ident d=depends TArob
+ { P.make_script_rule_name_result scr lang d }
+
+extends:
+ /* empty */ { () }
+| TExtends parent=TRuleName
+ { !Data.install_bindings (parent) }
+
+depends:
+ /* empty */ { Ast.NoDep }
+| TDepends TOn parents=dep { parents }
+
+dep:
+ pnrule { $1 }
+| dep TAndLog dep { Ast.AndDep($1, $3) }
+| dep TOrLog dep { Ast.OrDep ($1, $3) }
+
+pnrule:
+ TRuleName { Ast.Dep $1 }
+| TBang TRuleName { Ast.AntiDep $2 }
+| TEver TRuleName { Ast.EverDep $2 }
+| TNever TRuleName { Ast.NeverDep $2 }
+| TOPar dep TCPar { $2 }
+
+choose_iso:
+ TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
+
+disable:
+ TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
+
+exists:
+ TExists { Ast.Exists }
+| TForall { Ast.Forall }
+| TReverse TForall { Ast.ReverseForall }
+| { Ast.Undetermined }
+
+is_expression: // for more flexible parsing of top level expressions
+ { false }
+| TExpression { true }
+
+include_main:
+ list(incl) TArob { $1 }
+| list(incl) TArobArob { $1 }
+
+incl:
+ TUsing TString { Common.Left(P.id2name $2) }
+| TUsing TPathIsoFile { Common.Right $2 }
+
+metadec:
+ ar=arity ispure=pure
+ kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+ { P.create_metadec ar ispure kindfn ids }
+| ar=arity ispure=pure
+ kindfn=metakind_atomic
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eq)) TMPtVirg
+ { P.create_metadec_ne ar ispure kindfn ids }
+| ar=arity ispure=pure
+ kindfn=metakind_atomic_expi
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eqe)) TMPtVirg
+ { P.create_metadec_ne ar ispure kindfn ids }
+| ar=arity ispure=pure
+ kindfn=metakind_atomic_expe
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_ceq)) TMPtVirg
+ { P.create_metadec_ne ar ispure kindfn ids }
+| ar=arity TPosition a=option(TPosAny)
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_pos)) TMPtVirg
+ { let kindfn arity name pure check_meta constraints =
+ let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
+ let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
+ !Data.add_pos_meta name constraints any; tok in
+ P.create_metadec_ne ar false kindfn ids }
+| ar=arity ispure=pure
+ TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
+ ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+ { P.create_len_metadec ar ispure
+ (fun lenname arity name pure check_meta ->
+ let tok =
+ check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
+ !Data.add_paramlist_meta name (Some lenname) pure; tok)
+ id ids }
+| ar=arity ispure=pure
+ TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
+ ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+ { P.create_len_metadec ar ispure
+ (fun lenname arity name pure check_meta ->
+ let tok =
+ check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
+ !Data.add_explist_meta name (Some lenname) pure; tok)
+ id ids }
+
+%inline metakind:
+ TFresh TIdentifier
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaFreshIdDecl(arity,name)) in
+ !Data.add_id_meta name [] pure; tok) }
+| TParameter
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
+ !Data.add_param_meta name pure; tok) }
+| TParameter Tlist
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
+ !Data.add_paramlist_meta name None pure; tok) }
+| TExpression Tlist
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
+ !Data.add_explist_meta name None pure; tok) }
+| TType
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
+ !Data.add_type_meta name pure; tok) }
+| TStatement
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
+ !Data.add_stm_meta name pure; tok) }
+| TStatement Tlist
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
+ !Data.add_stmlist_meta name pure; tok) }
+| TTypedef
+ { (fun arity (_,name) pure check_meta ->
+ if arity = Ast.NONE && pure = Ast0.Impure
+ then (!Data.add_type_name name; [])
+ else raise (Semantic_cocci.Semantic "bad typedef")) }
+| TDeclarer TName
+ { (fun arity (_,name) pure check_meta ->
+ if arity = Ast.NONE && pure = Ast0.Impure
+ then (!Data.add_declarer_name name; [])
+ else raise (Semantic_cocci.Semantic "bad declarer")) }
+| TIterator TName
+ { (fun arity (_,name) pure check_meta ->
+ if arity = Ast.NONE && pure = Ast0.Impure
+ then (!Data.add_iterator_name name; [])
+ else raise (Semantic_cocci.Semantic "bad iterator")) }
+
+
+%inline metakind_atomic:
+ TIdentifier
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
+ !Data.add_id_meta name constraints pure; tok) }
+| TFunction
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
+ !Data.add_func_meta name constraints pure; tok) }
+| TLocal TFunction
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
+ !Data.add_local_func_meta name constraints pure;
+ tok) }
+| TDeclarer
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
+ !Data.add_declarer_meta name constraints pure; tok) }
+| TIterator
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
+ !Data.add_iterator_meta name constraints pure; tok) }
+
+%inline metakind_atomic_expi:
+ TError
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
+ !Data.add_err_meta name constraints pure; tok) }
+| l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
+ { (fun arity name pure check_meta constraints ->
+ match l with
+ None ->
+ !Data.add_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaIdExpDecl(arity,name,ty))
+ | Some _ ->
+ !Data.add_local_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
+| l=option(TLocal) TIdExpression m=nonempty_list(TMul)
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
+ match l with
+ None ->
+ !Data.add_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaIdExpDecl(arity,name,ty))
+ | Some _ ->
+ !Data.add_local_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
+| TExpression m=nonempty_list(TMul)
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
+ !Data.add_exp_meta ty name constraints pure; tok) }
+| vl=meta_exp_type TOCro TCCro
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
+ !Data.add_exp_meta ty name constraints pure; tok) }
+| TConstant ty=ioption(meta_exp_type)
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
+ !Data.add_const_meta ty name constraints pure; tok) }
+
+%inline metakind_atomic_expe:
+ TExpression
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
+ !Data.add_exp_meta None name constraints pure; tok) }
+| vl=meta_exp_type // no error if use $1 but doesn't type check
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some vl in
+ List.iter
+ (function c ->
+ match Ast0.unwrap c with
+ Ast0.Constant(_) ->
+ if not
+ (List.exists
+ (function
+ Type_cocci.BaseType(Type_cocci.IntType,_) -> true
+ | Type_cocci.BaseType(Type_cocci.ShortType,_) -> true
+ | Type_cocci.BaseType(Type_cocci.LongType,_) -> true
+ | _ -> false)
+ vl)
+ then failwith "metavariable with int constraint must be an int"
+ | _ -> ())
+ constraints;
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
+ !Data.add_exp_meta ty name constraints pure; tok) }
+
+
+meta_exp_type:
+ t=ctype
+ { [Ast0_cocci.ast0_type_to_type t] }
+| TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
+ { List.map
+ (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
+ t }
+
+arity: TBang0 { Ast.UNIQUE }
+ | TWhy0 { Ast.OPT }
+ | TPlus0 { Ast.MULTI }
+ | /* empty */ { Ast.NONE }
+
+generic_ctype:
+ q=ctype_qualif
+ { Ast0.wrap(Ast0.ImplicitInt(q)) }
+ | q=ioption(ctype_qualif) ty=Tchar
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.CharType ty, q)) }
+ | q=ioption(ctype_qualif) ty=Tshort
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.ShortType ty, q)) }
+ | q=ioption(ctype_qualif) ty=Tint
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.IntType ty, q)) }
+ | t=Tdouble
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.DoubleType t, None)) }
+ | t=Tfloat
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.FloatType t, None)) }
+ | q=ioption(ctype_qualif) ty=Tlong
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.LongType ty, q)) }
+ | s=struct_or_union i=ident
+ { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
+ | s=struct_or_union i=ioption(ident)
+ l=TOBrace d=struct_decl_list r=TCBrace
+ { (if i = None && !Data.in_iso
+ then failwith "structures must be named in the iso file");
+ Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
+ P.clt2mcode "{" l,
+ d, P.clt2mcode "}" r)) }
+ | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
+ { let (nm,pure,clt) = s in
+ let ty =
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
+ Ast0.wrap
+ (Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
+ | r=TRuleName TDot p=TIdent
+ { let nm = (r,P.id2name p) in
+ (* this is only possible when we are in a metavar decl. Otherwise,
+ it will be represented already as a MetaType *)
+ let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
+ Ast0.Impure (*will be ignored*))) }
+ | p=TTypeId
+ { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
+ | p=TMetaType
+ { let (nm,pure,clt) = p in
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
+
+struct_or_union:
+ s=Tstruct { P.clt2mcode Ast.Struct s }
+ | u=Tunion { P.clt2mcode Ast.Union u }
+
+struct_decl:
+ TNothing { [] }
+ | t=ctype d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
+ | t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
+ | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
+
+struct_decl_list:
+ struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
+
+struct_decl_list_start:
+ struct_decl { $1 }
+| struct_decl struct_decl_list_start { $1@$2 }
+| d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
+ { (P.mkddots "..." d)::r }
+
+continue_struct_decl_list:
+ /* empty */ { [] }
+| struct_decl struct_decl_list_start { $1@$2 }
+| struct_decl { $1 }
+
+ctype:
+ cv=ioption(const_vol) ty=generic_ctype m=list(TMul)
+ { P.pointerify (P.make_cv cv ty) m }
+ | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
+ { let ty =
+ Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
+ P.pointerify (P.make_cv cv ty) m }
+ | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
+ /* more hacks */
+ { let (mids,code) = t in
+ Ast0.wrap
+ (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
+
+
+fn_ctype: // allows metavariables
+ ty=generic_ctype m=list(TMul) { P.pointerify ty m }
+ | t=Tvoid m=list(TMul)
+ { P.pointerify
+ (Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)))
+ m }
+
+ctype_qualif:
+ Tunsigned { P.clt2mcode Ast.Unsigned $1 }
+ | Tsigned { P.clt2mcode Ast.Signed $1 }
+
+/*****************************************************************************/
+
+/* have to inline everything to avoid conflicts? switch to proper
+declarations, statements, and expressions for the subterms */
+
+minus_body:
+ f=loption(filespec)
+ b=loption(minus_start)
+ ew=loption(error_words)
+ { match f@b@ew with
+ [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
+ | code -> Top_level.top_level code }
+
+plus_body:
+ f=loption(filespec)
+ b=loption(plus_start)
+ ew=loption(error_words)
+ { Top_level.top_level (f@b@ew) }
+
+minus_exp_body:
+ f=loption(filespec)
+ b=top_eexpr
+ ew=loption(error_words)
+ { match f@[b]@ew with
+ [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
+ | code -> Top_level.top_level code }
+
+plus_exp_body:
+ f=loption(filespec)
+ b=top_eexpr
+ ew=loption(error_words)
+ { Top_level.top_level (f@[b]@ew) }
+
+filespec:
+ TMinusFile TPlusFile
+ { [Ast0.wrap
+ (Ast0.FILEINFO(P.id2mcode $1,
+ P.id2mcode $2))] }
+
+includes:
+ TIncludeL
+ { Ast0.wrap
+ (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
+ let (arity,ln,lln,offset,col,strbef,straft,pos) =
+ P.id2clt $1 in
+ let clt =
+ (arity,ln,lln,offset,0,strbef,straft,pos) in
+ P.clt2mcode
+ (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
+ (P.drop_bef clt))) }
+| TIncludeNL
+ { Ast0.wrap
+ (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
+ let (arity,ln,lln,offset,col,strbef,straft,pos) =
+ P.id2clt $1 in
+ let clt =
+ (arity,ln,lln,offset,0,strbef,straft,pos) in
+ P.clt2mcode
+ (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
+ (P.drop_bef clt))) }
+| d=defineop t=ctype TLineEnd
+ { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
+ d (Ast0.wrap(Ast0.DOTS([ty]))) }
+| defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
+ { let body =
+ match b with
+ [e] ->
+ (match Ast0.unwrap e with
+ Ast0.Exp(e1) ->
+ [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
+ | _ -> b)
+ | _ -> b in
+ $1 (Ast0.wrap(Ast0.DOTS(body))) }
+
+defineop:
+ TDefine
+ { let (clt,ident) = $1 in
+ function body ->
+ Ast0.wrap
+ (Ast0.Define
+ (P.clt2mcode "#define" clt,
+ (match ident with
+ TMetaId((nm,constraints,pure,clt)) ->
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
+ | TIdent(nm_pure) ->
+ Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ "unexpected name for a #define")),
+ Ast0.wrap Ast0.NoParams,
+ body)) }
+| TDefineParam define_param_list_option TCPar
+ { let (clt,ident,parenoff) = $1 in
+ let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
+ let lp =
+ P.clt2mcode "(" (arity,line,lline,parenoff,0,[],[],Ast0.NoMetaPos) in
+ function body ->
+ Ast0.wrap
+ (Ast0.Define
+ (P.clt2mcode "#define" clt,
+ (match ident with
+ TMetaId((nm,constraints,pure,clt)) ->
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
+ | TIdent(nm_pure) ->
+ Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ "unexpected name for a #define")),
+ Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
+
+/* ---------------------------------------------------------------------- */
+
+define_param_list: define_param_list_start
+ {let circle x =
+ match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
+ if List.exists circle $1
+ then Ast0.wrap(Ast0.CIRCLES($1))
+ else Ast0.wrap(Ast0.DOTS($1)) }
+
+define_param_list_start:
+ ident { [Ast0.wrap(Ast0.DParam $1)] }
+ | ident TComma define_param_list_start
+ { Ast0.wrap(Ast0.DParam $1)::
+ Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
+ | d=TEllipsis r=list(dp_comma_args(TEllipsis))
+ { (P.mkdpdots "..." d)::
+ (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
+
+dp_comma_args(dotter):
+ c=TComma d=dotter
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
+| TComma ident
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
+ Ast0.wrap(Ast0.DParam $2)] }
+
+define_param_list_option: define_param_list { $1 }
+ | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
+
+/*****************************************************************************/
+
+funproto:
+ s=ioption(storage) t=ctype
+ id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
+ { Ast0.wrap
+ (Ast0.UnInit
+ (s,
+ Ast0.wrap
+ (Ast0.FunctionType(Some t,
+ P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
+ id, P.clt2mcode ";" pt)) }
+| s=ioption(storage) t=Tvoid
+ id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
+ { let t = Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
+ Ast0.wrap
+ (Ast0.UnInit
+ (s,
+ Ast0.wrap
+ (Ast0.FunctionType(Some t,
+ P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
+ id, P.clt2mcode ";" pt)) }
+
+
+fundecl:
+ f=fninfo
+ TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
+ lb=TOBrace b=fun_start rb=TCBrace
+ { Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
+ f, i,
+ P.clt2mcode "(" lp, d,
+ P.clt2mcode ")" rp,
+ P.clt2mcode "{" lb, b,
+ P.clt2mcode "}" rb)) }
+
+fninfo:
+ /* empty */ { [] }
+ | storage fninfo
+ { try
+ let _ =
+ List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate storage")
+ with Not_found -> (Ast0.FStorage($1))::$2 }
+ | t=fn_ctype r=fninfo_nt { (Ast0.FType(t))::r }
+ | Tinline fninfo
+ { try
+ let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate inline")
+ with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
+ | Tattr fninfo
+ { try
+ let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "multiple attributes")
+ with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
+
+fninfo_nt:
+ /* empty */ { [] }
+ | storage fninfo_nt
+ { try
+ let _ =
+ List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate storage")
+ with Not_found -> (Ast0.FStorage($1))::$2 }
+ | Tinline fninfo_nt
+ { try
+ let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate inline")
+ with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
+ | Tattr fninfo_nt
+ { try
+ let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate init")
+ with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
+
+storage:
+ s=Tstatic { P.clt2mcode Ast.Static s }
+ | s=Tauto { P.clt2mcode Ast.Auto s }
+ | s=Tregister { P.clt2mcode Ast.Register s }
+ | s=Textern { P.clt2mcode Ast.Extern s }
+
+decl: t=ctype i=ident
+ { Ast0.wrap(Ast0.Param(t, Some i)) }
+ | t=fn_ctype lp=TOPar s=TMul i=ident rp=TCPar
+ lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
+ { let fnptr =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
+ P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
+ Ast0.wrap(Ast0.Param(fnptr, Some i)) }
+ | t=Tvoid
+ { let ty = Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
+ Ast0.wrap(Ast0.VoidParam(ty)) }
+ | TMetaParam
+ { let (nm,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
+
+name_opt_decl:
+ decl { $1 }
+ | t=ctype { Ast0.wrap(Ast0.Param(t, None)) }
+ | t=fn_ctype lp=TOPar s=TMul rp=TCPar
+ lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
+ { let fnptr =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
+ P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
+ Ast0.wrap(Ast0.Param(fnptr, None)) }
+
+const_vol:
+ Tconst { P.clt2mcode Ast.Const $1 }
+ | Tvolatile { P.clt2mcode Ast.Volatile $1 }
+
+/*****************************************************************************/
+
+statement:
+ includes { $1 } /* shouldn't be allowed to be a single_statement... */
+| TMetaStm
+ { P.meta_stm $1 }
+| expr TPtVirg
+ { P.exp_stm $1 $2 }
+| TIf TOPar eexpr TCPar single_statement %prec TIf
+ { P.ifthen $1 $2 $3 $4 $5 }
+| TIf TOPar eexpr TCPar single_statement TElse single_statement
+ { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
+| TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
+ option(eexpr) TCPar single_statement
+ { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
+| TWhile TOPar eexpr TCPar single_statement
+ { P.whileloop $1 $2 $3 $4 $5 }
+| TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
+ { P.doloop $1 $2 $3 $4 $5 $6 $7 }
+| iter_ident TOPar eexpr_list_option TCPar single_statement
+ { P.iterator $1 $2 $3 $4 $5 }
+| TSwitch TOPar eexpr TCPar TOBrace list(case_line) TCBrace
+ { P.switch $1 $2 $3 $4 $5 $6 $7 }
+| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
+| TReturn TPtVirg { P.ret $1 $2 }
+| TBreak TPtVirg { P.break $1 $2 }
+| TContinue TPtVirg { P.cont $1 $2 }
+| ident TDotDot { P.label $1 $2 }
+| TGoto ident TPtVirg { P.goto $1 $2 $3 }
+| TOBrace fun_start TCBrace
+ { P.seq $1 $2 $3 }
+
+stm_dots:
+ TEllipsis w=list(whenppdecs)
+ { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
+| TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
+ { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
+ P.clt2mcode "...>" c, List.concat w, false)) }
+| TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
+ { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
+ P.clt2mcode "...+>" c, List.concat w, true)) }
+
+whenppdecs: w=whens(when_start,rule_elem_statement)
+ { w }
+
+/* a statement that fits into a single rule_elem. should nests be included?
+what about statement metavariables? */
+rule_elem_statement:
+ one_decl_var
+ { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
+| expr TPtVirg { P.exp_stm $1 $2 }
+| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
+| TReturn TPtVirg { P.ret $1 $2 }
+| TBreak TPtVirg { P.break $1 $2 }
+| TContinue TPtVirg { P.cont $1 $2 }
+| TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
+ { let (mids,code) = $2 in
+ Ast0.wrap
+ (Ast0.Disj(P.clt2mcode "(" $1,
+ List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
+ mids, P.clt2mcode ")" $3)) }
+
+/* a statement on its own */
+single_statement:
+ statement { $1 }
+ | TOPar0 midzero_list(statement,statement) TCPar0
+ /* degenerate case, elements are single statements and thus don't
+ contain dots */
+ { let (mids,code) = $2 in
+ Ast0.wrap
+ (Ast0.Disj(P.clt2mcode "(" $1,
+ List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
+ mids, P.clt2mcode ")" $3)) }
+
+case_line:
+ TDefault TDotDot fun_start
+ { Ast0.wrap(Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
+ | TCase eexpr TDotDot fun_start
+ { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
+
+/* In the following, an identifier as a type is not fully supported. Indeed,
+the language is ambiguous: what is foo * bar; */
+/* The AST DisjDecl cannot be generated because it would be ambiguous with
+a disjunction on a statement with a declaration in each branch */
+decl_var:
+ t=ctype pv=TPtVirg
+ { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
+ | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
+ { List.map
+ (function (id,fn) ->
+ Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
+ d }
+ | f=funproto { [f] }
+ | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
+ {let (id,fn) = d in
+ [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
+ /* type is a typedef name */
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
+ d=comma_list(d_ident) pv=TPtVirg
+ { List.map
+ (function (id,fn) ->
+ let idtype =
+ P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
+ d }
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
+ e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ !Data.add_type_name (P.id2name i);
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
+ P.clt2mcode ";" pv))] }
+ /* function pointer type */
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
+ | decl_ident TOPar eexpr_list_option TCPar TPtVirg
+ { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
+ P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ q=TEq e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
+ | s=Ttypedef t=ctype id=typedef_ident pv=TPtVirg
+ { let s = P.clt2mcode "typedef" s in
+ [Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] }
+
+one_decl_var:
+ t=ctype pv=TPtVirg
+ { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
+ | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
+ | f=funproto { f }
+ | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
+ /* type is a typedef name */
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
+ d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
+ e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ !Data.add_type_name (P.id2name i);
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
+ P.clt2mcode ";" pv)) }
+ /* function pointer type */
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
+ | decl_ident TOPar eexpr_list_option TCPar TPtVirg
+ { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
+ P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ q=TEq e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
+
+
+d_ident:
+ ident list(array_dec)
+ { ($1,
+ function t ->
+ List.fold_right
+ (function (l,i,r) ->
+ function rest ->
+ Ast0.wrap
+ (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
+ $2 t) }
+
+array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
+
+initialize:
+ eexpr
+ { Ast0.wrap(Ast0.InitExpr($1)) }
+ | TOBrace initialize_list TCBrace
+ { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
+ | TOBrace TCBrace
+ { Ast0.wrap
+ (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
+ P.clt2mcode "}" $2)) }
+
+initialize2:
+ /*arithexpr and not eexpr because can have ambiguity with comma*/
+ /*dots and nests probably not allowed at top level, haven't looked into why*/
+ arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
+| TOBrace initialize_list TCBrace
+ { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
+| TOBrace TCBrace
+ { Ast0.wrap
+ (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
+ P.clt2mcode "}" $2)) }
+ /* gccext:, labeled elements */
+| TDot ident TEq initialize2
+ { Ast0.wrap(Ast0.InitGccDotName(P.clt2mcode "." $1,$2,P.clt2mcode "=" $3,$4)) }
+| ident TDotDot initialize2
+ { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
+| TOCro eexpr TCCro TEq initialize2
+ { Ast0.wrap(Ast0.InitGccIndex(P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3,
+ P.clt2mcode "=" $4,$5)) }
+| TOCro eexpr TEllipsis eexpr TCCro TEq initialize2
+ { Ast0.wrap(Ast0.InitGccRange(P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
+ $4,P.clt2mcode "]" $5,P.clt2mcode "=" $6,$7)) }
+
+initialize_list:
+ initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
+
+initialize_list_start:
+ initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
+| initialize2 TComma initialize_list_start
+ { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
+| d=edots_when(TEllipsis,initialize)
+ r=comma_initializers(edots_when(TEllipsis,initialize))
+ { (P.mkidots "..." d)::
+ (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
+
+comma_initializers(dotter):
+ /* empty */ { [] }
+| d=dotter r=comma_initializers2(dotter)
+ { (function dot_builder -> [dot_builder d])::r }
+| i=initialize2 c=TComma r=comma_initializers(dotter)
+ { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
+ r }
+
+comma_initializers2(dotter):
+ /* empty */ { [] }
+| i=initialize2 c=TComma r=comma_initializers(dotter)
+ { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
+ r }
+
+/* a statement that is part of a list */
+decl_statement:
+ TMetaStmList
+ { let (nm,pure,clt) = $1 in
+ [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
+ | decl_var
+ { List.map
+ (function x ->
+ Ast0.wrap
+ (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
+ $1 }
+ | statement { [$1] }
+ /* this doesn't allow expressions at top level, because the parser doesn't
+ know whether there is one. If there is one, this is not sequencible.
+ If there is not one, then it is. It seems complicated to get around
+ this at the parser level. We would have to have a check afterwards to
+ allow this. One case where this would be useful is for a when. Now
+ we allow a sequence of whens, so one can be on only statements and
+ one can be on only expressions. */
+ | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
+ { let (mids,code) = t in
+ if List.for_all
+ (function x ->
+ match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
+ code
+ then []
+ else
+ [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
+ P.clt2mcode ")" $3))] }
+
+/* a statement that is part of a list */
+decl_statement_expr:
+ TMetaStmList
+ { let (nm,pure,clt) = $1 in
+ [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
+ | decl_var
+ { List.map
+ (function x ->
+ Ast0.wrap
+ (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
+ $1 }
+ | statement { [$1] }
+ /* this doesn't allow expressions at top level, because the parser doesn't
+ know whether there is one. If there is one, this is not sequencible.
+ If there is not one, then it is. It seems complicated to get around
+ this at the parser level. We would have to have a check afterwards to
+ allow this. One case where this would be useful is for a when. Now
+ we allow a sequence of whens, so one can be on only statements and
+ one can be on only expressions. */
+ | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
+ { let (mids,code) = t in
+ if List.for_all (function [] -> true | _ -> false) code
+ then []
+ else
+ let dot_code =
+ List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
+ [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
+ P.clt2mcode ")" $3))] }
+
+/*****************************************************************************/
+
+/* The following cannot contain <... ...> at the top level. This can only
+be allowed as an expression when the expression is delimited on both sides
+by expression-specific markers. In that case, the rule eexpr is used, which
+allows <... ...> anywhere. Hopefully, this will not be too much of a problem
+in practice. */
+expr: basic_expr(expr,invalid) { $1 }
+/* allows ... and nests */
+eexpr: basic_expr(eexpr,dot_expressions) { $1 }
+/* allows nests but not .... */
+dexpr: basic_expr(eexpr,nest_expressions) { $1 }
+
+top_eexpr:
+ eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
+
+invalid:
+ TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
+
+dot_expressions:
+ TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
+| nest_expressions { $1 }
+
+nest_expressions:
+ TOEllipsis w=option(whenexp) e=expr_dots(TEllipsis) c=TCEllipsis
+ { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
+ Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
+ P.clt2mcode "...>" c, w, false)) }
+| TPOEllipsis w=option(whenexp) e=expr_dots(TEllipsis) c=TPCEllipsis
+ { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
+ Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
+ P.clt2mcode "...+>" c, w, true)) }
+
+whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
+
+basic_expr(recurser,primary_extra):
+ assign_expr(recurser,primary_extra) { $1 }
+
+assign_expr(r,pe):
+ cond_expr(r,pe) { $1 }
+ | unary_expr(r,pe) TAssign assign_expr_bis
+ { let (op,clt) = $2 in
+ Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
+ Ast0.set_arg_exp $3,false)) }
+ | unary_expr(r,pe) TEq assign_expr_bis
+ { Ast0.wrap
+ (Ast0.Assignment
+ ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
+
+assign_expr_bis:
+ cond_expr(eexpr,dot_expressions) { $1 }
+ | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
+ { let (op,clt) = $2 in
+ Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
+ Ast0.set_arg_exp $3,false)) }
+ | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
+ { Ast0.wrap
+ (Ast0.Assignment
+ ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
+
+cond_expr(r,pe):
+ arith_expr(r,pe) { $1 }
+ | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
+ { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
+ P.clt2mcode ":" dd, r)) }
+
+arith_expr(r,pe):
+ cast_expr(r,pe) { $1 }
+ | arith_expr(r,pe) TMul arith_expr(r,pe)
+ { P.arith_op Ast.Mul $1 $2 $3 }
+ | arith_expr(r,pe) TDmOp arith_expr(r,pe)
+ { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+ | arith_expr(r,pe) TPlus arith_expr(r,pe)
+ { P.arith_op Ast.Plus $1 $2 $3 }
+ | arith_expr(r,pe) TMinus arith_expr(r,pe)
+ { P.arith_op Ast.Minus $1 $2 $3 }
+ | arith_expr(r,pe) TShOp arith_expr(r,pe)
+ { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+ | arith_expr(r,pe) TLogOp arith_expr(r,pe)
+ { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
+ | arith_expr(r,pe) TEqEq arith_expr(r,pe)
+ { P.logic_op Ast.Eq $1 $2 $3 }
+ | arith_expr(r,pe) TNotEq arith_expr(r,pe)
+ { P.logic_op Ast.NotEq $1 $2 $3 }
+ | arith_expr(r,pe) TAnd arith_expr(r,pe)
+ { P.arith_op Ast.And $1 $2 $3 }
+ | arith_expr(r,pe) TOr arith_expr(r,pe)
+ { P.arith_op Ast.Or $1 $2 $3 }
+ | arith_expr(r,pe) TXor arith_expr(r,pe)
+ { P.arith_op Ast.Xor $1 $2 $3 }
+ | arith_expr(r,pe) TAndLog arith_expr(r,pe)
+ { P.logic_op Ast.AndLog $1 $2 $3 }
+ | arith_expr(r,pe) TOrLog arith_expr(r,pe)
+ { P.logic_op Ast.OrLog $1 $2 $3 }
+
+cast_expr(r,pe):
+ unary_expr(r,pe) { $1 }
+ | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
+ { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
+ P.clt2mcode ")" rp, e)) }
+
+unary_expr(r,pe):
+ postfix_expr(r,pe) { $1 }
+ | TInc unary_expr(r,pe)
+ { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
+ | TDec unary_expr(r,pe)
+ { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
+ | unary_op unary_expr(r,pe)
+ { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
+ | TBang unary_expr(r,pe)
+ { let mcode = P.clt2mcode Ast.Not $1 in
+ Ast0.wrap(Ast0.Unary($2, mcode)) }
+ | TSizeof unary_expr(r,pe)
+ { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
+ | s=TSizeof lp=TOPar t=ctype rp=TCPar
+ { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
+ P.clt2mcode "(" lp,t,
+ P.clt2mcode ")" rp)) }
+
+unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
+ | TMul { P.clt2mcode Ast.DeRef $1 }
+ | TPlus { P.clt2mcode Ast.UnPlus $1 }
+ | TMinus { P.clt2mcode Ast.UnMinus $1 }
+ | TTilde { P.clt2mcode Ast.Tilde $1 }
+
+postfix_expr(r,pe):
+ primary_expr(r,pe) { $1 }
+ | postfix_expr(r,pe) TOCro eexpr TCCro
+ { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
+ P.clt2mcode "]" $4)) }
+ | postfix_expr(r,pe) TDot ident
+ { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
+ | postfix_expr(r,pe) TPtrOp ident
+ { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
+ $3)) }
+ | postfix_expr(r,pe) TInc
+ { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
+ | postfix_expr(r,pe) TDec
+ { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
+ | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
+ { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
+ $3,
+ P.clt2mcode ")" $4)) }
+
+primary_expr(recurser,primary_extra):
+ func_ident { Ast0.wrap(Ast0.Ident($1)) }
+ | TInt
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
+ | TFloat
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
+ | TString
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
+ | TChar
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
+ | TMetaConst
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
+ | TMetaErr
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
+ | TMetaExp
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
+ | TMetaIdExp
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
+ | TMetaLocalIdExp
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
+ | TOPar eexpr TCPar
+ { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
+ P.clt2mcode ")" $3)) }
+ | TOPar0 midzero_list(recurser,eexpr) TCPar0
+ { let (mids,code) = $2 in
+ Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
+ code, mids,
+ P.clt2mcode ")" $3)) }
+ | primary_extra { $1 }
+
+expr_dots(dotter):
+ r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
+
+// used in NEST
+no_dot_start_end(grammar,dotter):
+ g=grammar dg=list(pair(dotter,grammar))
+ { function dot_builder ->
+ g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
+
+/*****************************************************************************/
+
+pure_ident:
+ TIdent { $1 }
+
+meta_ident:
+ TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
+
+pure_ident_or_meta_ident:
+ pure_ident { (None,P.id2name $1) }
+ | meta_ident { $1 }
+ | Tlist { (None,"list") }
+ | TError { (None,"error") }
+ | TType { (None,"type") }
+
+pure_ident_or_meta_ident_with_not_eq(not_eq):
+ i=pure_ident_or_meta_ident l=loption(not_eq) { (i,l) }
+
+not_eq:
+ TNotEq i=pure_ident
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ [Ast0.wrap(Ast0.Id(P.id2mcode i))] }
+ | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l }
+
+not_eqe:
+ TNotEq i=pure_ident
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] }
+ | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ List.map
+ (function i ->
+ Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
+ l }
+
+not_ceq:
+ TNotEq i=ident_or_const
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ [i] }
+ | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ l }
+
+ident_or_const:
+ i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
+ | TInt
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
+
+not_pos:
+ TNotEq i=meta_ident
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ match i with
+ (None,_) -> failwith "constraint must be an inherited variable"
+ | (Some rule,name) ->
+ let i = (rule,name) in
+ P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
+ [i] }
+ | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ List.map
+ (function
+ (None,_) ->
+ failwith "constraint must be an inherited variable"
+ | (Some rule,name) ->
+ let i = (rule,name) in
+ P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
+ i)
+ l }
+
+func_ident: pure_ident
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaId
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+ | TMetaFunc
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
+ | TMetaLocalFunc
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
+
+ident: pure_ident
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaId
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+
+decl_ident:
+ TDeclarerId
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaDeclarer
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+
+iter_ident:
+ TIteratorId
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaIterator
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+
+typedef_ident:
+ pure_ident
+ { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
+ | TMetaType
+ { let (nm,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
+
+/*****************************************************************************/
+
+decl_list(decl):
+ decl_list_start(decl)
+ {let circle x =
+ match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
+ if List.exists circle $1
+ then Ast0.wrap(Ast0.CIRCLES($1))
+ else Ast0.wrap(Ast0.DOTS($1)) }
+
+decl_list_start(decl):
+ one_dec(decl) { [$1] }
+| one_dec(decl) TComma decl_list_start(decl)
+ { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
+| TEllipsis list(comma_decls(TEllipsis,decl))
+ { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
+ (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
+
+one_dec(decl):
+ decl { $1 }
+| TMetaParamList
+ { let (nm,lenname,pure,clt) = $1 in
+ let nm = P.clt2mcode nm clt in
+ let lenname =
+ match lenname with
+ Some nm -> Some(P.clt2mcode nm clt)
+ | None -> None in
+ Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
+
+comma_decls(dotter,decl):
+ TComma dotter
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
+ dot_builder $2] }
+| TComma one_dec(decl)
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
+
+/* ---------------------------------------------------------------------- */
+
+error_words:
+ TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
+ { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
+
+/* ---------------------------------------------------------------------- */
+/* sequences of statements and expressions */
+
+/* There are number of cases that must be considered:
+
+1. Top level:
+ Dots and nests allowed at the beginning or end
+ Expressions allowed at the beginning or end
+ One function allowed, by itself
+2. A function body:
+ Dots and nests allowed at the beginning or end
+ Expressions not allowed at the beginning or end
+ Functions not allowed
+3. The body of a nest:
+ Dots and nests not allowed at the beginning or end
+ Expressions allowed at the beginning or end
+ Functions not allowed
+4. Whencode:
+ Dots and nests not allowed at the beginning but allowed at the end
+ Expressions allowed at the beginning or end
+ Functions not allowed
+
+These are implemented by the rules minus_toplevel_sequence,
+plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
+when_body_sequence.
+*/
+/* ------------------------------------------------------------------------ */
+/* Minus top level */
+
+/* doesn't allow only ... */
+minus_start:
+ fundecl { [Ast0.wrap(Ast0.DECL($1))] }
+| ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
+| toplevel_seq_start(toplevel_after_dots_init)
+ { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
+
+toplevel_seq_start(after_dots_init):
+ stm_dots after_dots_init { $1::$2 }
+| expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
+| decl_statement_expr toplevel_after_stm { $1@$2 }
+
+toplevel_after_dots_init:
+ TNothing toplevel_after_exp {$2}
+| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
+| decl_statement_expr toplevel_after_stm {$1@$2}
+
+toplevel_after_exp:
+ /* empty */ {[]}
+| stm_dots toplevel_after_dots {$1::$2}
+
+toplevel_after_dots:
+ /* empty */ {[]}
+| TNothing toplevel_after_exp {$2}
+| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
+| decl_statement_expr toplevel_after_stm {$1@$2}
+
+toplevel_after_stm:
+ /* empty */ {[]}
+| stm_dots toplevel_after_dots {$1::$2}
+| decl_statement toplevel_after_stm {$1@$2}
+
+/* ------------------------------------------------------------------------ */
+/* Plus top level */
+
+/* does allow only ... also allows multiple top-level functions */
+plus_start:
+ ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
+| stm_dots plus_after_dots
+ { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
+| expr plus_after_exp
+ { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
+| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
+| decl_statement_expr plus_after_stm
+ { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
+
+plus_after_exp:
+ /* empty */ {[]}
+| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
+
+plus_after_dots:
+ /* empty */ {[]}
+| TNothing plus_after_exp {$2}
+| expr plus_after_exp
+ { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
+| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
+| decl_statement_expr plus_after_stm
+ { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
+
+plus_after_stm:
+ /* empty */ {[]}
+| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
+| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
+| decl_statement plus_after_stm
+ { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
+
+/* ------------------------------------------------------------------------ */
+/* Function body */
+
+fun_start:
+ fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
+
+fun_after_stm:
+ /* empty */ {[]}
+| stm_dots fun_after_dots {$1::$2}
+| decl_statement fun_after_stm {$1@$2}
+
+fun_after_dots:
+ /* empty */ {[]}
+| TNothing fun_after_exp {$2}
+| expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
+| decl_statement_expr fun_after_stm {$1@$2}
+
+fun_after_exp:
+ stm_dots fun_after_dots {$1::$2}
+
+/* hack to allow mixing statements and expressions in an or */
+fun_after_dots_or:
+ /* empty */ {[]}
+| TNothing fun_after_exp_or {$2}
+| expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
+| decl_statement_expr fun_after_stm {$1@$2}
+
+fun_after_exp_or:
+ /* empty */ {[]}
+| stm_dots fun_after_dots {$1::$2}
+
+/* ------------------------------------------------------------------------ */
+/* Nest body */
+
+nest_start:
+ nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
+
+nest_after_dots:
+ decl_statement_expr nest_after_stm {$1@$2}
+| TNothing nest_after_exp {$2}
+| expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
+
+nest_after_stm:
+ /* empty */ {[]}
+| stm_dots nest_after_dots {$1::$2}
+| decl_statement nest_after_stm {$1@$2}
+
+nest_after_exp:
+ /* empty */ {[]}
+| stm_dots nest_after_dots {$1::$2}
+
+/* ------------------------------------------------------------------------ */
+/*Whencode*/
+
+when_start:
+ expr toplevel_after_exp
+ { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
+| decl_statement toplevel_after_stm
+ { Ast0.wrap(Ast0.DOTS($1@$2)) }
+
+/* ---------------------------------------------------------------------- */
+
+eexpr_list:
+ eexpr_list_start
+ {let circle x =
+ match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
+ let star x =
+ match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
+ if List.exists circle $1
+ then Ast0.wrap(Ast0.CIRCLES($1))
+ else
+ if List.exists star $1
+ then Ast0.wrap(Ast0.STARS($1))
+ else Ast0.wrap(Ast0.DOTS($1)) }
+
+/* arg expr. may contain a type or a explist metavariable */
+aexpr:
+ eexpr
+ { Ast0.set_arg_exp $1 }
+ | TMetaExpList
+ { let (nm,lenname,pure,clt) = $1 in
+ let nm = P.clt2mcode nm clt in
+ let lenname =
+ match lenname with
+ Some nm -> Some(P.clt2mcode nm clt)
+ | None -> None in
+ Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
+ | ctype
+ { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
+
+eexpr_list_start:
+ aexpr { [$1] }
+ | aexpr TComma eexpr_list_start
+ { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
+
+comma_args(dotter):
+ c=TComma d=dotter
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
+| TComma aexpr
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
+
+eexpr_list_option: eexpr_list { $1 }
+ | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
+
+/****************************************************************************/
+
+// non-empty lists - drop separator
+comma_list(elem):
+ separated_nonempty_list(TComma,elem) { $1 }
+
+midzero_list(elem,aft):
+ a=elem b=list(mzl(aft))
+ { let (mids,code) = List.split b in (mids,(a::code)) }
+
+mzl(elem):
+ a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
+
+edots_when(dotter,when_grammar):
+ d=dotter { (d,None) }
+ | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
+
+dots_when(dotter,when_grammar,simple_when_grammar):
+ d=dotter w=list(whens(when_grammar,simple_when_grammar))
+ { (d,List.concat w) }
+
+whens(when_grammar,simple_when_grammar):
+ TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
+ | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
+ | TWhen comma_list(any_strict) TLineEnd
+ { List.map (function x -> Ast0.WhenModifier(x)) $2 }
+
+any_strict:
+ TAny { Ast.WhenAny }
+ | TStrict { Ast.WhenStrict }
+ | TForall { Ast.WhenForall }
+ | TExists { Ast.WhenExists }
+
+/*****************************************************************************
+*
+*
+*****************************************************************************/
+
+iso_main:
+ TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
+ { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
+| TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
+ { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
+| TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
+ { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
+| TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
+ { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
+| TIsoType t1=ctype tl=list(iso(ctype)) EOF
+ { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
+| TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
+ { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
+| TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
+ { let check_one = function
+ [x] -> x
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ "only one variable per declaration in an isomorphism rule") in
+ let d1 = check_one d1 in
+ let dl =
+ List.map
+ (function
+ Common.Left x -> Common.Left(check_one x)
+ | Common.Right x -> Common.Right(check_one x))
+ dl in
+ P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
+
+iso(term):
+ TIso t=term { Common.Left t }
+ | TRightIso t=term { Common.Right t }
+
+/*****************************************************************************
+*
+*
+*****************************************************************************/
+
+never_used: TPragma { () }
+ | TPArob TMetaPos { () }
+ | TScriptData { () }
+
+script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
+ { (P.id2name py, ($3, P.id2name cocci)) }
--- /dev/null
+/*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*/
+
+
+%{
+
+(* Not clear how to allow function declarations to specify a return type
+and how to allow both to be specified as static, because they are in
+different rules. The rules seem to have to be combined, which would allow
+functions to be declared as local variables *)
+
+(* Not clear how to let a function have a parameter of type void. At the
+moment, void is allowed to be the type of a variable, which is wrong, and a
+parameter needs both a type and an identifier *)
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module P = Parse_aux
+%}
+
+%token EOF
+
+%token TIdentifier TExpression TStatement TFunction TLocal TType TParameter
+%token TIdExpression
+%token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
+%token TPure TContext
+%token TTypedef TDeclarer TIterator TName TPosition TPosAny
+%token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall TScript
+%token TReverse TNothing
+%token<string> TRuleName
+
+%token<Data.clt> Tchar Tshort Tint Tdouble Tfloat Tlong
+%token<Data.clt> Tvoid Tstruct Tunion
+%token<Data.clt> Tunsigned Tsigned
+
+%token<Data.clt> Tstatic Tauto Tregister Textern Tinline Ttypedef
+%token<Data.clt> Tconst Tvolatile
+%token<string * Data.clt> Tattr
+
+%token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
+%token <Data.clt> TBreak TContinue TGoto TSizeof TFunDecl
+%token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
+
+%token <Parse_aux.idinfo> TMetaId TMetaFunc TMetaLocalFunc
+%token <Parse_aux.idinfo> TMetaIterator TMetaDeclarer
+%token <Parse_aux.expinfo> TMetaErr
+%token <Parse_aux.info> TMetaParam TMetaStm TMetaStmList TMetaType
+%token <Parse_aux.list_info> TMetaParamList TMetaExpList
+%token <Parse_aux.typed_info> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
+%token <Parse_aux.pos_info> TMetaPos
+
+%token TArob TArobArob TPArob
+%token <string> TScriptData
+
+%token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
+%token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
+
+%token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
+%token <Data.clt> TMid0 TCPar TCPar0
+
+%token <string> TPragma TPathIsoFile
+%token <string * Data.clt> TIncludeL TIncludeNL
+%token <Data.clt * token> TDefine
+%token <Data.clt * token * int> TDefineParam
+%token <string * Data.clt> TMinusFile TPlusFile
+
+%token <Data.clt> TInc TDec
+
+%token <string * Data.clt> TString TChar TFloat TInt
+
+%token <Data.clt> TOrLog
+%token <Data.clt> TAndLog
+%token <Data.clt> TOr
+%token <Data.clt> TXor
+%token <Data.clt> TAnd
+%token <Data.clt> TEqEq TNotEq
+%token <Ast_cocci.logicalOp * Data.clt> TLogOp /* TInf TSup TInfEq TSupEq */
+%token <Ast_cocci.arithOp * Data.clt> TShOp /* TShl TShr */
+%token <Ast_cocci.arithOp * Data.clt> TDmOp /* TDiv TMod */
+%token <Data.clt> TPlus TMinus
+%token <Data.clt> TMul TTilde
+
+%token <Data.clt> TOBrace TCBrace
+%token <Data.clt> TOCro TCCro
+
+%token <Data.clt> TPtrOp
+
+%token TMPtVirg
+%token <Data.clt> TEq TDot TComma TPtVirg
+%token <Ast_cocci.assignOp * Data.clt> TAssign
+
+%token TIso TRightIso TIsoExpression TIsoStatement TIsoDeclaration TIsoType
+%token TIsoTopLevel TIsoArgExpression TIsoTestExpression
+
+%token TInvalid
+
+/* operator precedence */
+%nonassoc TIf
+%nonassoc TElse
+
+%left TOrLog
+%left TAndLog
+%left TOr
+%left TXor
+%left TAnd
+%left TEqEq TNotEq
+%left TLogOp /* TInf TSup TInfEq TSupEq */
+%left TShOp /* TShl TShr */
+%left TPlus TMinus
+%left TMul TDmOp /* TDiv TMod */
+
+%start reinit
+%type <unit> reinit
+
+%start minus_main
+%type <Ast0_cocci.rule> minus_main
+
+%start minus_exp_main
+%type <Ast0_cocci.rule> minus_exp_main
+
+%start plus_main
+%type <Ast0_cocci.rule> plus_main
+
+%start plus_exp_main
+%type <Ast0_cocci.rule> plus_exp_main
+
+%start include_main
+%type <(string,string) Common.either list> include_main
+
+%start iso_rule_name
+%type <Ast_cocci.rulename>
+iso_rule_name
+
+%start rule_name
+%type <Ast_cocci.rulename>
+rule_name
+
+%start meta_main
+%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> meta_main
+
+%start <string * (string * string)> script_meta_main
+
+%start iso_main
+%type <Ast0_cocci.anything list list> iso_main
+
+%start iso_meta_main
+%type <(Ast_cocci.metavar,Ast_cocci.metavar) Common.either list> iso_meta_main
+
+%start never_used
+%type <unit> never_used
+
+%%
+
+reinit: { }
+minus_main: minus_body EOF { $1 } | m=minus_body TArobArob { m }
+| m=minus_body TArob { m }
+plus_main: plus_body EOF { $1 } | p=plus_body TArobArob { p }
+| p=plus_body TArob { p }
+minus_exp_main: minus_exp_body EOF { $1 } | m=minus_exp_body TArobArob { m }
+| m=minus_exp_body TArob { m }
+plus_exp_main: plus_exp_body EOF { $1 } | p=plus_exp_body TArobArob { p }
+| p=plus_exp_body TArob { p }
+meta_main: m=metadec { m (!Ast0.rule_name) }
+iso_meta_main: m=metadec { m "" }
+
+/*****************************************************************************
+*
+*
+*****************************************************************************/
+
+pure:
+ TPure { Ast0.Pure }
+| TContext { Ast0.Context }
+| TPure TContext { Ast0.PureContext }
+| TContext TPure { Ast0.PureContext }
+| /* empty */ { Ast0.Impure }
+
+iso_rule_name:
+ nm=pure_ident TArob { P.make_iso_rule_name_result (P.id2name nm) }
+
+rule_name:
+ nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
+ a=loption(disable) e=exists ee=is_expression TArob
+ { P.make_cocci_rule_name_result nm d i a e ee }
+ | TScript TDotDot lang=pure_ident d=depends TArob
+ { P.make_script_rule_name_result lang d }
+
+extends:
+ /* empty */ { () }
+| TExtends parent=TRuleName
+ { !Data.install_bindings (parent) }
+
+depends:
+ /* empty */ { Ast.NoDep }
+| TDepends TOn parents=dep { parents }
+
+dep:
+ pnrule { $1 }
+| dep TAndLog dep { Ast.AndDep($1, $3) }
+| dep TOrLog dep { Ast.OrDep ($1, $3) }
+
+pnrule:
+ TRuleName { Ast.Dep $1 }
+| TBang TRuleName { Ast.AntiDep $2 }
+| TEver TRuleName { Ast.EverDep $2 }
+| TNever TRuleName { Ast.NeverDep $2 }
+| TOPar dep TCPar { $2 }
+
+choose_iso:
+ TUsing separated_nonempty_list(TComma,TString) { List.map P.id2name $2 }
+
+disable:
+ TDisable separated_nonempty_list(TComma,pure_ident) { List.map P.id2name $2 }
+
+exists:
+ TExists { Ast.Exists }
+| TForall { Ast.Forall }
+| TReverse TForall { Ast.ReverseForall }
+| { Ast.Undetermined }
+
+is_expression: // for more flexible parsing of top level expressions
+ { false }
+| TExpression { true }
+
+include_main:
+ list(incl) TArob { $1 }
+| list(incl) TArobArob { $1 }
+
+incl:
+ TUsing TString { Common.Left(P.id2name $2) }
+| TUsing TPathIsoFile { Common.Right $2 }
+
+metadec:
+ ar=arity ispure=pure
+ kindfn=metakind ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+ { P.create_metadec ar ispure kindfn ids }
+| ar=arity ispure=pure
+ kindfn=metakind_atomic
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eq)) TMPtVirg
+ { P.create_metadec_ne ar ispure kindfn ids }
+| ar=arity ispure=pure
+ kindfn=metakind_atomic_expi
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_eqe)) TMPtVirg
+ { P.create_metadec_ne ar ispure kindfn ids }
+| ar=arity ispure=pure
+ kindfn=metakind_atomic_expe
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_ceq)) TMPtVirg
+ { P.create_metadec_ne ar ispure kindfn ids }
+| ar=arity TPosition a=option(TPosAny)
+ ids=comma_list(pure_ident_or_meta_ident_with_not_eq(not_pos)) TMPtVirg
+ { let kindfn arity name pure check_meta constraints =
+ let tok = check_meta(Ast.MetaPosDecl(arity,name)) in
+ let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
+ !Data.add_pos_meta name constraints any; tok in
+ P.create_metadec_ne ar false kindfn ids }
+| ar=arity ispure=pure
+ TParameter Tlist TOCro id=pure_ident_or_meta_ident TCCro
+ ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+ { P.create_len_metadec ar ispure
+ (fun lenname arity name pure check_meta ->
+ let tok =
+ check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
+ !Data.add_paramlist_meta name (Some lenname) pure; tok)
+ id ids }
+| ar=arity ispure=pure
+ TExpression Tlist TOCro id=pure_ident_or_meta_ident TCCro
+ ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+ { P.create_len_metadec ar ispure
+ (fun lenname arity name pure check_meta ->
+ let tok =
+ check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
+ !Data.add_explist_meta name (Some lenname) pure; tok)
+ id ids }
+
+%inline metakind:
+ TFresh TIdentifier
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaFreshIdDecl(arity,name)) in
+ !Data.add_id_meta name [] pure; tok) }
+| TParameter
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
+ !Data.add_param_meta name pure; tok) }
+| TParameter Tlist
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
+ !Data.add_paramlist_meta name None pure; tok) }
+| TExpression Tlist
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
+ !Data.add_explist_meta name None pure; tok) }
+| TType
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
+ !Data.add_type_meta name pure; tok) }
+| TStatement
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
+ !Data.add_stm_meta name pure; tok) }
+| TStatement Tlist
+ { (fun arity name pure check_meta ->
+ let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
+ !Data.add_stmlist_meta name pure; tok) }
+| TTypedef
+ { (fun arity (_,name) pure check_meta ->
+ if arity = Ast.NONE && pure = Ast0.Impure
+ then (!Data.add_type_name name; [])
+ else raise (Semantic_cocci.Semantic "bad typedef")) }
+| TDeclarer TName
+ { (fun arity (_,name) pure check_meta ->
+ if arity = Ast.NONE && pure = Ast0.Impure
+ then (!Data.add_declarer_name name; [])
+ else raise (Semantic_cocci.Semantic "bad declarer")) }
+| TIterator TName
+ { (fun arity (_,name) pure check_meta ->
+ if arity = Ast.NONE && pure = Ast0.Impure
+ then (!Data.add_iterator_name name; [])
+ else raise (Semantic_cocci.Semantic "bad iterator")) }
+
+
+%inline metakind_atomic:
+ TIdentifier
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
+ !Data.add_id_meta name constraints pure; tok) }
+| TFunction
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
+ !Data.add_func_meta name constraints pure; tok) }
+| TLocal TFunction
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
+ !Data.add_local_func_meta name constraints pure;
+ tok) }
+| TDeclarer
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
+ !Data.add_declarer_meta name constraints pure; tok) }
+| TIterator
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
+ !Data.add_iterator_meta name constraints pure; tok) }
+
+%inline metakind_atomic_expi:
+ TError
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
+ !Data.add_err_meta name constraints pure; tok) }
+| l=option(TLocal) TIdExpression ty=ioption(meta_exp_type)
+ { (fun arity name pure check_meta constraints ->
+ match l with
+ None ->
+ !Data.add_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaIdExpDecl(arity,name,ty))
+ | Some _ ->
+ !Data.add_local_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
+| l=option(TLocal) TIdExpression m=nonempty_list(TMul)
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
+ match l with
+ None ->
+ !Data.add_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaIdExpDecl(arity,name,ty))
+ | Some _ ->
+ !Data.add_local_idexp_meta ty name constraints pure;
+ check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) }
+| TExpression m=nonempty_list(TMul)
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
+ !Data.add_exp_meta ty name constraints pure; tok) }
+| vl=meta_exp_type TOCro TCCro
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
+ !Data.add_exp_meta ty name constraints pure; tok) }
+| TConstant ty=ioption(meta_exp_type)
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
+ !Data.add_const_meta ty name constraints pure; tok) }
+
+%inline metakind_atomic_expe:
+ TExpression
+ { (fun arity name pure check_meta constraints ->
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
+ !Data.add_exp_meta None name constraints pure; tok) }
+| vl=meta_exp_type // no error if use $1 but doesn't type check
+ { (fun arity name pure check_meta constraints ->
+ let ty = Some vl in
+ List.iter
+ (function c ->
+ match Ast0.unwrap c with
+ Ast0.Constant(_) ->
+ if not
+ (List.exists
+ (function
+ Type_cocci.BaseType(Type_cocci.IntType,_) -> true
+ | Type_cocci.BaseType(Type_cocci.ShortType,_) -> true
+ | Type_cocci.BaseType(Type_cocci.LongType,_) -> true
+ | _ -> false)
+ vl)
+ then failwith "metavariable with int constraint must be an int"
+ | _ -> ())
+ constraints;
+ let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
+ !Data.add_exp_meta ty name constraints pure; tok) }
+
+
+meta_exp_type:
+ t=ctype
+ { [Ast0_cocci.ast0_type_to_type t] }
+| TOBrace t=comma_list(ctype) TCBrace m=list(TMul)
+ { List.map
+ (function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
+ t }
+
+arity: TBang0 { Ast.UNIQUE }
+ | TWhy0 { Ast.OPT }
+ | TPlus0 { Ast.MULTI }
+ | /* empty */ { Ast.NONE }
+
+generic_ctype:
+ q=ctype_qualif
+ { Ast0.wrap(Ast0.ImplicitInt(q)) }
+ | q=ioption(ctype_qualif) ty=Tchar
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.CharType ty, q)) }
+ | q=ioption(ctype_qualif) ty=Tshort
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.ShortType ty, q)) }
+ | q=ioption(ctype_qualif) ty=Tint
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.IntType ty, q)) }
+ | t=Tdouble
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.DoubleType t, None)) }
+ | t=Tfloat
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.FloatType t, None)) }
+ | q=ioption(ctype_qualif) ty=Tlong
+ { Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.LongType ty, q)) }
+ | s=struct_or_union i=ident
+ { Ast0.wrap(Ast0.StructUnionName(s, Some i)) }
+ | s=struct_or_union i=ioption(ident)
+ l=TOBrace d=struct_decl_list r=TCBrace
+ { (if i = None && !Data.in_iso
+ then failwith "structures must be named in the iso file");
+ Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
+ P.clt2mcode "{" l,
+ d, P.clt2mcode "}" r)) }
+ | s=TMetaType l=TOBrace d=struct_decl_list r=TCBrace
+ { let (nm,pure,clt) = s in
+ let ty =
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
+ Ast0.wrap
+ (Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) }
+ | r=TRuleName TDot p=TIdent
+ { let nm = (r,P.id2name p) in
+ (* this is only possible when we are in a metavar decl. Otherwise,
+ it will be represented already as a MetaType *)
+ let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
+ Ast0.Impure (*will be ignored*))) }
+ | p=TTypeId
+ { Ast0.wrap(Ast0.TypeName(P.id2mcode p)) }
+ | p=TMetaType
+ { let (nm,pure,clt) = p in
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
+
+struct_or_union:
+ s=Tstruct { P.clt2mcode Ast.Struct s }
+ | u=Tunion { P.clt2mcode Ast.Union u }
+
+struct_decl:
+ TNothing { [] }
+ | t=ctype d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
+ | t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ [Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] }
+ | cv=ioption(const_vol) i=pure_ident d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ [Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] }
+
+struct_decl_list:
+ struct_decl_list_start { Ast0.wrap(Ast0.DOTS($1)) }
+
+struct_decl_list_start:
+ struct_decl { $1 }
+| struct_decl struct_decl_list_start { $1@$2 }
+| d=edots_when(TEllipsis,struct_decl) r=continue_struct_decl_list
+ { (P.mkddots "..." d)::r }
+
+continue_struct_decl_list:
+ /* empty */ { [] }
+| struct_decl struct_decl_list_start { $1@$2 }
+| struct_decl { $1 }
+
+ctype:
+ cv=ioption(const_vol) ty=generic_ctype m=list(TMul)
+ { P.pointerify (P.make_cv cv ty) m }
+ | cv=ioption(const_vol) t=Tvoid m=nonempty_list(TMul)
+ { let ty =
+ Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
+ P.pointerify (P.make_cv cv ty) m }
+ | lp=TOPar0 t=midzero_list(ctype,ctype) rp=TCPar0
+ /* more hacks */
+ { let (mids,code) = t in
+ Ast0.wrap
+ (Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
+
+
+fn_ctype: // allows metavariables
+ ty=generic_ctype m=list(TMul) { P.pointerify ty m }
+ | t=Tvoid m=list(TMul)
+ { P.pointerify
+ (Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)))
+ m }
+
+ctype_qualif:
+ Tunsigned { P.clt2mcode Ast.Unsigned $1 }
+ | Tsigned { P.clt2mcode Ast.Signed $1 }
+
+/*****************************************************************************/
+
+/* have to inline everything to avoid conflicts? switch to proper
+declarations, statements, and expressions for the subterms */
+
+minus_body:
+ f=loption(filespec)
+ b=loption(minus_start)
+ ew=loption(error_words)
+ { match f@b@ew with
+ [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
+ | code -> Top_level.top_level code }
+
+plus_body:
+ f=loption(filespec)
+ b=loption(plus_start)
+ ew=loption(error_words)
+ { Top_level.top_level (f@b@ew) }
+
+minus_exp_body:
+ f=loption(filespec)
+ b=top_eexpr
+ ew=loption(error_words)
+ { match f@[b]@ew with
+ [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
+ | code -> Top_level.top_level code }
+
+plus_exp_body:
+ f=loption(filespec)
+ b=top_eexpr
+ ew=loption(error_words)
+ { Top_level.top_level (f@[b]@ew) }
+
+filespec:
+ TMinusFile TPlusFile
+ { [Ast0.wrap
+ (Ast0.FILEINFO(P.id2mcode $1,
+ P.id2mcode $2))] }
+
+includes:
+ TIncludeL
+ { Ast0.wrap
+ (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
+ let (arity,ln,lln,offset,col,strbef,straft,pos) =
+ P.id2clt $1 in
+ let clt =
+ (arity,ln,lln,offset,0,strbef,straft,pos) in
+ P.clt2mcode
+ (Ast.Local (Parse_aux.str2inc (P.id2name $1)))
+ (P.drop_bef clt))) }
+| TIncludeNL
+ { Ast0.wrap
+ (Ast0.Include(P.clt2mcode "#include" (P.drop_aft (P.id2clt $1)),
+ let (arity,ln,lln,offset,col,strbef,straft,pos) =
+ P.id2clt $1 in
+ let clt =
+ (arity,ln,lln,offset,0,strbef,straft,pos) in
+ P.clt2mcode
+ (Ast.NonLocal (Parse_aux.str2inc (P.id2name $1)))
+ (P.drop_bef clt))) }
+| d=defineop t=ctype TLineEnd
+ { let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
+ d (Ast0.wrap(Ast0.DOTS([ty]))) }
+| defineop b=toplevel_seq_start(toplevel_after_dots) TLineEnd
+ { let body =
+ match b with
+ [e] ->
+ (match Ast0.unwrap e with
+ Ast0.Exp(e1) ->
+ [Ast0.rewrap e (Ast0.TopExp(Ast0.set_arg_exp (e1)))]
+ | _ -> b)
+ | _ -> b in
+ $1 (Ast0.wrap(Ast0.DOTS(body))) }
+
+defineop:
+ TDefine
+ { let (clt,ident) = $1 in
+ function body ->
+ Ast0.wrap
+ (Ast0.Define
+ (P.clt2mcode "#define" clt,
+ (match ident with
+ TMetaId((nm,constraints,pure,clt)) ->
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
+ | TIdent(nm_pure) ->
+ Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ "unexpected name for a #define")),
+ Ast0.wrap Ast0.NoParams,
+ body)) }
+| TDefineParam define_param_list_option TCPar
+ { let (clt,ident,parenoff) = $1 in
+ let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
+ let lp =
+ P.clt2mcode "(" (arity,line,lline,parenoff,0,[],[],Ast0.NoMetaPos) in
+ function body ->
+ Ast0.wrap
+ (Ast0.Define
+ (P.clt2mcode "#define" clt,
+ (match ident with
+ TMetaId((nm,constraints,pure,clt)) ->
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
+ | TIdent(nm_pure) ->
+ Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ "unexpected name for a #define")),
+ Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
+
+/* ---------------------------------------------------------------------- */
+
+define_param_list: define_param_list_start
+ {let circle x =
+ match Ast0.unwrap x with Ast0.DPcircles(_) -> true | _ -> false in
+ if List.exists circle $1
+ then Ast0.wrap(Ast0.CIRCLES($1))
+ else Ast0.wrap(Ast0.DOTS($1)) }
+
+define_param_list_start:
+ ident { [Ast0.wrap(Ast0.DParam $1)] }
+ | ident TComma define_param_list_start
+ { Ast0.wrap(Ast0.DParam $1)::
+ Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $2))::$3 }
+ | d=TEllipsis r=list(dp_comma_args(TEllipsis))
+ { (P.mkdpdots "..." d)::
+ (List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) }
+
+dp_comma_args(dotter):
+ c=TComma d=dotter
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] }
+| TComma ident
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.DPComma(P.clt2mcode "," $1));
+ Ast0.wrap(Ast0.DParam $2)] }
+
+define_param_list_option: define_param_list { $1 }
+ | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
+
+/*****************************************************************************/
+
+funproto:
+ s=ioption(storage) t=ctype
+ id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
+ { Ast0.wrap
+ (Ast0.UnInit
+ (s,
+ Ast0.wrap
+ (Ast0.FunctionType(Some t,
+ P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
+ id, P.clt2mcode ";" pt)) }
+| s=ioption(storage) t=Tvoid
+ id=func_ident lp=TOPar d=decl_list(name_opt_decl) rp=TCPar pt=TPtVirg
+ { let t = Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
+ Ast0.wrap
+ (Ast0.UnInit
+ (s,
+ Ast0.wrap
+ (Ast0.FunctionType(Some t,
+ P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
+ id, P.clt2mcode ";" pt)) }
+
+
+fundecl:
+ f=fninfo
+ TFunDecl i=func_ident lp=TOPar d=decl_list(decl) rp=TCPar
+ lb=TOBrace b=fun_start rb=TCBrace
+ { Ast0.wrap(Ast0.FunDecl((Ast0.default_info(),Ast0.context_befaft()),
+ f, i,
+ P.clt2mcode "(" lp, d,
+ P.clt2mcode ")" rp,
+ P.clt2mcode "{" lb, b,
+ P.clt2mcode "}" rb)) }
+
+fninfo:
+ /* empty */ { [] }
+ | storage fninfo
+ { try
+ let _ =
+ List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate storage")
+ with Not_found -> (Ast0.FStorage($1))::$2 }
+ | t=fn_ctype r=fninfo_nt { (Ast0.FType(t))::r }
+ | Tinline fninfo
+ { try
+ let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate inline")
+ with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
+ | Tattr fninfo
+ { try
+ let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "multiple attributes")
+ with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
+
+fninfo_nt:
+ /* empty */ { [] }
+ | storage fninfo_nt
+ { try
+ let _ =
+ List.find (function Ast0.FStorage(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate storage")
+ with Not_found -> (Ast0.FStorage($1))::$2 }
+ | Tinline fninfo_nt
+ { try
+ let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate inline")
+ with Not_found -> (Ast0.FInline(P.clt2mcode "inline" $1))::$2 }
+ | Tattr fninfo_nt
+ { try
+ let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) $2 in
+ raise (Semantic_cocci.Semantic "duplicate init")
+ with Not_found -> (Ast0.FAttr(P.id2mcode $1))::$2 }
+
+storage:
+ s=Tstatic { P.clt2mcode Ast.Static s }
+ | s=Tauto { P.clt2mcode Ast.Auto s }
+ | s=Tregister { P.clt2mcode Ast.Register s }
+ | s=Textern { P.clt2mcode Ast.Extern s }
+
+decl: t=ctype i=ident
+ { Ast0.wrap(Ast0.Param(t, Some i)) }
+ | t=fn_ctype lp=TOPar s=TMul i=ident rp=TCPar
+ lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
+ { let fnptr =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
+ P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
+ Ast0.wrap(Ast0.Param(fnptr, Some i)) }
+ | t=Tvoid
+ { let ty = Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
+ Ast0.wrap(Ast0.VoidParam(ty)) }
+ | TMetaParam
+ { let (nm,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) }
+
+name_opt_decl:
+ decl { $1 }
+ | t=ctype { Ast0.wrap(Ast0.Param(t, None)) }
+ | t=fn_ctype lp=TOPar s=TMul rp=TCPar
+ lp1=TOPar d=decl_list(name_opt_decl) rp1=TCPar
+ { let fnptr =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
+ P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
+ Ast0.wrap(Ast0.Param(fnptr, None)) }
+
+const_vol:
+ Tconst { P.clt2mcode Ast.Const $1 }
+ | Tvolatile { P.clt2mcode Ast.Volatile $1 }
+
+/*****************************************************************************/
+
+statement:
+ includes { $1 } /* shouldn't be allowed to be a single_statement... */
+| TMetaStm
+ { P.meta_stm $1 }
+| expr TPtVirg
+ { P.exp_stm $1 $2 }
+| TIf TOPar eexpr TCPar single_statement %prec TIf
+ { P.ifthen $1 $2 $3 $4 $5 }
+| TIf TOPar eexpr TCPar single_statement TElse single_statement
+ { P.ifthenelse $1 $2 $3 $4 $5 $6 $7 }
+| TFor TOPar option(eexpr) TPtVirg option(eexpr) TPtVirg
+ option(eexpr) TCPar single_statement
+ { P.forloop $1 $2 $3 $4 $5 $6 $7 $8 $9 }
+| TWhile TOPar eexpr TCPar single_statement
+ { P.whileloop $1 $2 $3 $4 $5 }
+| TDo single_statement TWhile TOPar eexpr TCPar TPtVirg
+ { P.doloop $1 $2 $3 $4 $5 $6 $7 }
+| iter_ident TOPar eexpr_list_option TCPar single_statement
+ { P.iterator $1 $2 $3 $4 $5 }
+| TSwitch TOPar eexpr TCPar TOBrace list(case_line) TCBrace
+ { P.switch $1 $2 $3 $4 $5 $6 $7 }
+| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
+| TReturn TPtVirg { P.ret $1 $2 }
+| TBreak TPtVirg { P.break $1 $2 }
+| TContinue TPtVirg { P.cont $1 $2 }
+| ident TDotDot { P.label $1 $2 }
+| TGoto ident TPtVirg { P.goto $1 $2 $3 }
+| TOBrace fun_start TCBrace
+ { P.seq $1 $2 $3 }
+
+stm_dots:
+ TEllipsis w=list(whenppdecs)
+ { Ast0.wrap(Ast0.Dots(P.clt2mcode "..." $1, List.concat w)) }
+| TOEllipsis w=list(whenppdecs) b=nest_start c=TCEllipsis
+ { Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." $1, b,
+ P.clt2mcode "...>" c, List.concat w, false)) }
+| TPOEllipsis w=list(whenppdecs) b=nest_start c=TPCEllipsis
+ { Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." $1, b,
+ P.clt2mcode "...+>" c, List.concat w, true)) }
+
+whenppdecs: w=whens(when_start,rule_elem_statement)
+ { w }
+
+/* a statement that fits into a single rule_elem. should nests be included?
+what about statement metavariables? */
+rule_elem_statement:
+ one_decl_var
+ { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
+| expr TPtVirg { P.exp_stm $1 $2 }
+| TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
+| TReturn TPtVirg { P.ret $1 $2 }
+| TBreak TPtVirg { P.break $1 $2 }
+| TContinue TPtVirg { P.cont $1 $2 }
+| TOPar0 midzero_list(rule_elem_statement,rule_elem_statement) TCPar0
+ { let (mids,code) = $2 in
+ Ast0.wrap
+ (Ast0.Disj(P.clt2mcode "(" $1,
+ List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
+ mids, P.clt2mcode ")" $3)) }
+
+/* a statement on its own */
+single_statement:
+ statement { $1 }
+ | TOPar0 midzero_list(statement,statement) TCPar0
+ /* degenerate case, elements are single statements and thus don't
+ contain dots */
+ { let (mids,code) = $2 in
+ Ast0.wrap
+ (Ast0.Disj(P.clt2mcode "(" $1,
+ List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
+ mids, P.clt2mcode ")" $3)) }
+
+case_line:
+ TDefault TDotDot fun_start
+ { Ast0.wrap(Ast0.Default(P.clt2mcode "default" $1,P.clt2mcode ":" $2,$3)) }
+ | TCase eexpr TDotDot fun_start
+ { Ast0.wrap(Ast0.Case(P.clt2mcode "case" $1,$2,P.clt2mcode ":" $3,$4)) }
+
+/* In the following, an identifier as a type is not fully supported. Indeed,
+the language is ambiguous: what is foo * bar; */
+/* The AST DisjDecl cannot be generated because it would be ambiguous with
+a disjunction on a statement with a declaration in each branch */
+decl_var:
+ t=ctype pv=TPtVirg
+ { [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] }
+ | s=ioption(storage) t=ctype d=comma_list(d_ident) pv=TPtVirg
+ { List.map
+ (function (id,fn) ->
+ Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
+ d }
+ | f=funproto { [f] }
+ | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
+ {let (id,fn) = d in
+ [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
+ /* type is a typedef name */
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
+ d=comma_list(d_ident) pv=TPtVirg
+ { List.map
+ (function (id,fn) ->
+ let idtype =
+ P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
+ d }
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
+ e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ !Data.add_type_name (P.id2name i);
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ [Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
+ P.clt2mcode ";" pv))] }
+ /* function pointer type */
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ [Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] }
+ | decl_ident TOPar eexpr_list_option TCPar TPtVirg
+ { [Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
+ P.clt2mcode ")" $4,P.clt2mcode ";" $5))] }
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ q=TEq e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ [Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))]}
+ | s=Ttypedef t=ctype id=typedef_ident pv=TPtVirg
+ { let s = P.clt2mcode "typedef" s in
+ [Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] }
+
+one_decl_var:
+ t=ctype pv=TPtVirg
+ { Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) }
+ | s=ioption(storage) t=ctype d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
+ | f=funproto { f }
+ | s=ioption(storage) t=ctype d=d_ident q=TEq e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) }
+ /* type is a typedef name */
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident
+ d=d_ident pv=TPtVirg
+ { let (id,fn) = d in
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) }
+ | s=ioption(storage) cv=ioption(const_vol) i=pure_ident d=d_ident q=TEq
+ e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ !Data.add_type_name (P.id2name i);
+ let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
+ Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
+ P.clt2mcode ";" pv)) }
+ /* function pointer type */
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) }
+ | decl_ident TOPar eexpr_list_option TCPar TPtVirg
+ { Ast0.wrap(Ast0.MacroDecl($1,P.clt2mcode "(" $2,$3,
+ P.clt2mcode ")" $4,P.clt2mcode ";" $5)) }
+ | s=ioption(storage)
+ t=fn_ctype lp1=TOPar st=TMul d=d_ident rp1=TCPar
+ lp2=TOPar p=decl_list(name_opt_decl) rp2=TCPar
+ q=TEq e=initialize pv=TPtVirg
+ { let (id,fn) = d in
+ let t =
+ Ast0.wrap
+ (Ast0.FunctionPointer
+ (t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
+ P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
+ Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))}
+
+
+d_ident:
+ ident list(array_dec)
+ { ($1,
+ function t ->
+ List.fold_right
+ (function (l,i,r) ->
+ function rest ->
+ Ast0.wrap
+ (Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
+ $2 t) }
+
+array_dec: l=TOCro i=option(eexpr) r=TCCro { (l,i,r) }
+
+initialize:
+ eexpr
+ { Ast0.wrap(Ast0.InitExpr($1)) }
+ | TOBrace initialize_list TCBrace
+ { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
+ | TOBrace TCBrace
+ { Ast0.wrap
+ (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
+ P.clt2mcode "}" $2)) }
+
+initialize2:
+ /*arithexpr and not eexpr because can have ambiguity with comma*/
+ /*dots and nests probably not allowed at top level, haven't looked into why*/
+ arith_expr(eexpr,invalid) { Ast0.wrap(Ast0.InitExpr($1)) }
+| TOBrace initialize_list TCBrace
+ { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
+| TOBrace TCBrace
+ { Ast0.wrap
+ (Ast0.InitList(P.clt2mcode "{" $1,Ast0.wrap(Ast0.DOTS []),
+ P.clt2mcode "}" $2)) }
+ /* gccext:, labeled elements */
+| TDot ident TEq initialize2
+ { Ast0.wrap(Ast0.InitGccDotName(P.clt2mcode "." $1,$2,P.clt2mcode "=" $3,$4)) }
+| ident TDotDot initialize2
+ { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
+| TOCro eexpr TCCro TEq initialize2
+ { Ast0.wrap(Ast0.InitGccIndex(P.clt2mcode "[" $1,$2,P.clt2mcode "]" $3,
+ P.clt2mcode "=" $4,$5)) }
+| TOCro eexpr TEllipsis eexpr TCCro TEq initialize2
+ { Ast0.wrap(Ast0.InitGccRange(P.clt2mcode "[" $1,$2,P.clt2mcode "..." $3,
+ $4,P.clt2mcode "]" $5,P.clt2mcode "=" $6,$7)) }
+
+initialize_list:
+ initialize_list_start { Ast0.wrap(Ast0.DOTS($1)) }
+
+initialize_list_start:
+ initialize2 TComma { [$1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))] }
+| initialize2 TComma initialize_list_start
+ { $1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," $2))::$3 }
+| d=edots_when(TEllipsis,initialize)
+ r=comma_initializers(edots_when(TEllipsis,initialize))
+ { (P.mkidots "..." d)::
+ (List.concat(List.map (function x -> x (P.mkidots "...")) r)) }
+
+comma_initializers(dotter):
+ /* empty */ { [] }
+| d=dotter r=comma_initializers2(dotter)
+ { (function dot_builder -> [dot_builder d])::r }
+| i=initialize2 c=TComma r=comma_initializers(dotter)
+ { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
+ r }
+
+comma_initializers2(dotter):
+ /* empty */ { [] }
+| i=initialize2 c=TComma r=comma_initializers(dotter)
+ { (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
+ r }
+
+/* a statement that is part of a list */
+decl_statement:
+ TMetaStmList
+ { let (nm,pure,clt) = $1 in
+ [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
+ | decl_var
+ { List.map
+ (function x ->
+ Ast0.wrap
+ (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
+ $1 }
+ | statement { [$1] }
+ /* this doesn't allow expressions at top level, because the parser doesn't
+ know whether there is one. If there is one, this is not sequencible.
+ If there is not one, then it is. It seems complicated to get around
+ this at the parser level. We would have to have a check afterwards to
+ allow this. One case where this would be useful is for a when. Now
+ we allow a sequence of whens, so one can be on only statements and
+ one can be on only expressions. */
+ | TOPar0 t=midzero_list(fun_start,fun_start) TCPar0
+ { let (mids,code) = t in
+ if List.for_all
+ (function x ->
+ match Ast0.unwrap x with Ast0.DOTS([]) -> true | _ -> false)
+ code
+ then []
+ else
+ [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, code, mids,
+ P.clt2mcode ")" $3))] }
+
+/* a statement that is part of a list */
+decl_statement_expr:
+ TMetaStmList
+ { let (nm,pure,clt) = $1 in
+ [Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] }
+ | decl_var
+ { List.map
+ (function x ->
+ Ast0.wrap
+ (Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
+ $1 }
+ | statement { [$1] }
+ /* this doesn't allow expressions at top level, because the parser doesn't
+ know whether there is one. If there is one, this is not sequencible.
+ If there is not one, then it is. It seems complicated to get around
+ this at the parser level. We would have to have a check afterwards to
+ allow this. One case where this would be useful is for a when. Now
+ we allow a sequence of whens, so one can be on only statements and
+ one can be on only expressions. */
+ | TOPar0 t=midzero_list(fun_after_stm,fun_after_dots_or) TCPar0
+ { let (mids,code) = t in
+ if List.for_all (function [] -> true | _ -> false) code
+ then []
+ else
+ let dot_code =
+ List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
+ [Ast0.wrap(Ast0.Disj(P.clt2mcode "(" $1, dot_code, mids,
+ P.clt2mcode ")" $3))] }
+
+/*****************************************************************************/
+
+/* The following cannot contain <... ...> at the top level. This can only
+be allowed as an expression when the expression is delimited on both sides
+by expression-specific markers. In that case, the rule eexpr is used, which
+allows <... ...> anywhere. Hopefully, this will not be too much of a problem
+in practice. */
+expr: basic_expr(expr,invalid) { $1 }
+/* allows ... and nests */
+eexpr: basic_expr(eexpr,dot_expressions) { $1 }
+/* allows nests but not .... */
+dexpr: basic_expr(eexpr,nest_expressions) { $1 }
+
+top_eexpr:
+ eexpr { Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))) }
+
+invalid:
+ TInvalid { raise (Semantic_cocci.Semantic "not matchable") }
+
+dot_expressions:
+ TEllipsis { Ast0.wrap(Ast0.Edots(P.clt2mcode "..." $1,None)) }
+| nest_expressions { $1 }
+
+nest_expressions:
+ TOEllipsis w=option(whenexp) e=expr_dots(TEllipsis) c=TCEllipsis
+ { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." $1,
+ Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
+ P.clt2mcode "...>" c, w, false)) }
+| TPOEllipsis w=option(whenexp) e=expr_dots(TEllipsis) c=TPCEllipsis
+ { Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." $1,
+ Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
+ P.clt2mcode "...+>" c, w, true)) }
+
+whenexp: TWhen TNotEq w=eexpr TLineEnd { w }
+
+basic_expr(recurser,primary_extra):
+ assign_expr(recurser,primary_extra) { $1 }
+
+assign_expr(r,pe):
+ cond_expr(r,pe) { $1 }
+ | unary_expr(r,pe) TAssign assign_expr_bis
+ { let (op,clt) = $2 in
+ Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
+ Ast0.set_arg_exp $3,false)) }
+ | unary_expr(r,pe) TEq assign_expr_bis
+ { Ast0.wrap
+ (Ast0.Assignment
+ ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
+
+assign_expr_bis:
+ cond_expr(eexpr,dot_expressions) { $1 }
+ | unary_expr(eexpr,dot_expressions) TAssign assign_expr_bis
+ { let (op,clt) = $2 in
+ Ast0.wrap(Ast0.Assignment($1,P.clt2mcode op clt,
+ Ast0.set_arg_exp $3,false)) }
+ | unary_expr(eexpr,dot_expressions) TEq assign_expr_bis
+ { Ast0.wrap
+ (Ast0.Assignment
+ ($1,P.clt2mcode Ast.SimpleAssign $2,Ast0.set_arg_exp $3,false)) }
+
+cond_expr(r,pe):
+ arith_expr(r,pe) { $1 }
+ | l=arith_expr(r,pe) w=TWhy t=option(eexpr) dd=TDotDot r=cond_expr(r,pe)
+ { Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
+ P.clt2mcode ":" dd, r)) }
+
+arith_expr(r,pe):
+ cast_expr(r,pe) { $1 }
+ | arith_expr(r,pe) TMul arith_expr(r,pe)
+ { P.arith_op Ast.Mul $1 $2 $3 }
+ | arith_expr(r,pe) TDmOp arith_expr(r,pe)
+ { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+ | arith_expr(r,pe) TPlus arith_expr(r,pe)
+ { P.arith_op Ast.Plus $1 $2 $3 }
+ | arith_expr(r,pe) TMinus arith_expr(r,pe)
+ { P.arith_op Ast.Minus $1 $2 $3 }
+ | arith_expr(r,pe) TShOp arith_expr(r,pe)
+ { let (op,clt) = $2 in P.arith_op op $1 clt $3 }
+ | arith_expr(r,pe) TLogOp arith_expr(r,pe)
+ { let (op,clt) = $2 in P.logic_op op $1 clt $3 }
+ | arith_expr(r,pe) TEqEq arith_expr(r,pe)
+ { P.logic_op Ast.Eq $1 $2 $3 }
+ | arith_expr(r,pe) TNotEq arith_expr(r,pe)
+ { P.logic_op Ast.NotEq $1 $2 $3 }
+ | arith_expr(r,pe) TAnd arith_expr(r,pe)
+ { P.arith_op Ast.And $1 $2 $3 }
+ | arith_expr(r,pe) TOr arith_expr(r,pe)
+ { P.arith_op Ast.Or $1 $2 $3 }
+ | arith_expr(r,pe) TXor arith_expr(r,pe)
+ { P.arith_op Ast.Xor $1 $2 $3 }
+ | arith_expr(r,pe) TAndLog arith_expr(r,pe)
+ { P.logic_op Ast.AndLog $1 $2 $3 }
+ | arith_expr(r,pe) TOrLog arith_expr(r,pe)
+ { P.logic_op Ast.OrLog $1 $2 $3 }
+
+cast_expr(r,pe):
+ unary_expr(r,pe) { $1 }
+ | lp=TOPar t=ctype rp=TCPar e=cast_expr(r,pe)
+ { Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
+ P.clt2mcode ")" rp, e)) }
+
+unary_expr(r,pe):
+ postfix_expr(r,pe) { $1 }
+ | TInc unary_expr(r,pe)
+ { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Inc $1)) }
+ | TDec unary_expr(r,pe)
+ { Ast0.wrap(Ast0.Infix ($2, P.clt2mcode Ast.Dec $1)) }
+ | unary_op unary_expr(r,pe)
+ { let mcode = $1 in Ast0.wrap(Ast0.Unary($2, mcode)) }
+ | TBang unary_expr(r,pe)
+ { let mcode = P.clt2mcode Ast.Not $1 in
+ Ast0.wrap(Ast0.Unary($2, mcode)) }
+ | TSizeof unary_expr(r,pe)
+ { Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" $1, $2)) }
+ | s=TSizeof lp=TOPar t=ctype rp=TCPar
+ { Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
+ P.clt2mcode "(" lp,t,
+ P.clt2mcode ")" rp)) }
+
+unary_op: TAnd { P.clt2mcode Ast.GetRef $1 }
+ | TMul { P.clt2mcode Ast.DeRef $1 }
+ | TPlus { P.clt2mcode Ast.UnPlus $1 }
+ | TMinus { P.clt2mcode Ast.UnMinus $1 }
+ | TTilde { P.clt2mcode Ast.Tilde $1 }
+
+postfix_expr(r,pe):
+ primary_expr(r,pe) { $1 }
+ | postfix_expr(r,pe) TOCro eexpr TCCro
+ { Ast0.wrap(Ast0.ArrayAccess ($1,P.clt2mcode "[" $2,$3,
+ P.clt2mcode "]" $4)) }
+ | postfix_expr(r,pe) TDot ident
+ { Ast0.wrap(Ast0.RecordAccess($1, P.clt2mcode "." $2, $3)) }
+ | postfix_expr(r,pe) TPtrOp ident
+ { Ast0.wrap(Ast0.RecordPtAccess($1, P.clt2mcode "->" $2,
+ $3)) }
+ | postfix_expr(r,pe) TInc
+ { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Inc $2)) }
+ | postfix_expr(r,pe) TDec
+ { Ast0.wrap(Ast0.Postfix ($1, P.clt2mcode Ast.Dec $2)) }
+ | postfix_expr(r,pe) TOPar eexpr_list_option TCPar
+ { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
+ $3,
+ P.clt2mcode ")" $4)) }
+
+primary_expr(recurser,primary_extra):
+ func_ident { Ast0.wrap(Ast0.Ident($1)) }
+ | TInt
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
+ | TFloat
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) }
+ | TString
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) }
+ | TChar
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) }
+ | TMetaConst
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) }
+ | TMetaErr
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) }
+ | TMetaExp
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) }
+ | TMetaIdExp
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) }
+ | TMetaLocalIdExp
+ { let (nm,constraints,pure,ty,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) }
+ | TOPar eexpr TCPar
+ { Ast0.wrap(Ast0.Paren(P.clt2mcode "(" $1,$2,
+ P.clt2mcode ")" $3)) }
+ | TOPar0 midzero_list(recurser,eexpr) TCPar0
+ { let (mids,code) = $2 in
+ Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" $1,
+ code, mids,
+ P.clt2mcode ")" $3)) }
+ | primary_extra { $1 }
+
+expr_dots(dotter):
+ r=no_dot_start_end(dexpr,edots_when(dotter,eexpr)) { r }
+
+// used in NEST
+no_dot_start_end(grammar,dotter):
+ g=grammar dg=list(pair(dotter,grammar))
+ { function dot_builder ->
+ g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) }
+
+/*****************************************************************************/
+
+pure_ident:
+ TIdent { $1 }
+
+meta_ident:
+ TRuleName TDot pure_ident { (Some $1,P.id2name $3) }
+
+pure_ident_or_meta_ident:
+ pure_ident { (None,P.id2name $1) }
+ | meta_ident { $1 }
+ | Tlist { (None,"list") }
+ | TError { (None,"error") }
+ | TType { (None,"type") }
+
+pure_ident_or_meta_ident_with_not_eq(not_eq):
+ i=pure_ident_or_meta_ident l=loption(not_eq) { (i,l) }
+
+not_eq:
+ TNotEq i=pure_ident
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ [Ast0.wrap(Ast0.Id(P.id2mcode i))] }
+ | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l }
+
+not_eqe:
+ TNotEq i=pure_ident
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ [Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] }
+ | TNotEq TOBrace l=comma_list(pure_ident) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ List.map
+ (function i ->
+ Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
+ l }
+
+not_ceq:
+ TNotEq i=ident_or_const
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ [i] }
+ | TNotEq TOBrace l=comma_list(ident_or_const) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ l }
+
+ident_or_const:
+ i=pure_ident { Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) }
+ | TInt
+ { let (x,clt) = $1 in
+ Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
+
+not_pos:
+ TNotEq i=meta_ident
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ match i with
+ (None,_) -> failwith "constraint must be an inherited variable"
+ | (Some rule,name) ->
+ let i = (rule,name) in
+ P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
+ [i] }
+ | TNotEq TOBrace l=comma_list(meta_ident) TCBrace
+ { (if !Data.in_iso
+ then failwith "constraints not allowed in iso file");
+ List.map
+ (function
+ (None,_) ->
+ failwith "constraint must be an inherited variable"
+ | (Some rule,name) ->
+ let i = (rule,name) in
+ P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
+ i)
+ l }
+
+func_ident: pure_ident
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaId
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+ | TMetaFunc
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
+ | TMetaLocalFunc
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap
+ (Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) }
+
+ident: pure_ident
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaId
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+
+decl_ident:
+ TDeclarerId
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaDeclarer
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+
+iter_ident:
+ TIteratorId
+ { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
+ | TMetaIterator
+ { let (nm,constraints,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+
+typedef_ident:
+ pure_ident
+ { Ast0.wrap(Ast0.TypeName(P.id2mcode $1)) }
+ | TMetaType
+ { let (nm,pure,clt) = $1 in
+ Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) }
+
+/*****************************************************************************/
+
+decl_list(decl):
+ decl_list_start(decl)
+ {let circle x =
+ match Ast0.unwrap x with Ast0.Pcircles(_) -> true | _ -> false in
+ if List.exists circle $1
+ then Ast0.wrap(Ast0.CIRCLES($1))
+ else Ast0.wrap(Ast0.DOTS($1)) }
+
+decl_list_start(decl):
+ one_dec(decl) { [$1] }
+| one_dec(decl) TComma decl_list_start(decl)
+ { $1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," $2))::$3 }
+| TEllipsis list(comma_decls(TEllipsis,decl))
+ { Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." $1))::
+ (List.concat(List.map (function x -> x (P.mkpdots "...")) $2)) }
+
+one_dec(decl):
+ decl { $1 }
+| TMetaParamList
+ { let (nm,lenname,pure,clt) = $1 in
+ let nm = P.clt2mcode nm clt in
+ let lenname =
+ match lenname with
+ Some nm -> Some(P.clt2mcode nm clt)
+ | None -> None in
+ Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) }
+
+comma_decls(dotter,decl):
+ TComma dotter
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1));
+ dot_builder $2] }
+| TComma one_dec(decl)
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.PComma(P.clt2mcode "," $1)); $2] }
+
+/* ---------------------------------------------------------------------- */
+
+error_words:
+ TError TWords TEq TOCro cl=comma_list(dexpr) TCCro
+ { [Ast0.wrap(Ast0.ERRORWORDS(cl))] }
+
+/* ---------------------------------------------------------------------- */
+/* sequences of statements and expressions */
+
+/* There are number of cases that must be considered:
+
+1. Top level:
+ Dots and nests allowed at the beginning or end
+ Expressions allowed at the beginning or end
+ One function allowed, by itself
+2. A function body:
+ Dots and nests allowed at the beginning or end
+ Expressions not allowed at the beginning or end
+ Functions not allowed
+3. The body of a nest:
+ Dots and nests not allowed at the beginning or end
+ Expressions allowed at the beginning or end
+ Functions not allowed
+4. Whencode:
+ Dots and nests not allowed at the beginning but allowed at the end
+ Expressions allowed at the beginning or end
+ Functions not allowed
+
+These are implemented by the rules minus_toplevel_sequence,
+plus_toplevel_sequence, function_body_sequence, nest_body_sequence, and
+when_body_sequence.
+*/
+/* ------------------------------------------------------------------------ */
+/* Minus top level */
+
+/* doesn't allow only ... */
+minus_start:
+ fundecl { [Ast0.wrap(Ast0.DECL($1))] }
+| ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
+| toplevel_seq_start(toplevel_after_dots_init)
+ { List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
+
+toplevel_seq_start(after_dots_init):
+ stm_dots after_dots_init { $1::$2 }
+| expr toplevel_after_exp { (Ast0.wrap(Ast0.Exp($1)))::$2 }
+| decl_statement_expr toplevel_after_stm { $1@$2 }
+
+toplevel_after_dots_init:
+ TNothing toplevel_after_exp {$2}
+| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
+| decl_statement_expr toplevel_after_stm {$1@$2}
+
+toplevel_after_exp:
+ /* empty */ {[]}
+| stm_dots toplevel_after_dots {$1::$2}
+
+toplevel_after_dots:
+ /* empty */ {[]}
+| TNothing toplevel_after_exp {$2}
+| expr toplevel_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
+| decl_statement_expr toplevel_after_stm {$1@$2}
+
+toplevel_after_stm:
+ /* empty */ {[]}
+| stm_dots toplevel_after_dots {$1::$2}
+| decl_statement toplevel_after_stm {$1@$2}
+
+/* ------------------------------------------------------------------------ */
+/* Plus top level */
+
+/* does allow only ... also allows multiple top-level functions */
+plus_start:
+ ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
+| stm_dots plus_after_dots
+ { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
+| expr plus_after_exp
+ { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
+| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
+| decl_statement_expr plus_after_stm
+ { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
+
+plus_after_exp:
+ /* empty */ {[]}
+| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
+
+plus_after_dots:
+ /* empty */ {[]}
+| TNothing plus_after_exp {$2}
+| expr plus_after_exp
+ { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
+| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
+| decl_statement_expr plus_after_stm
+ { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
+
+plus_after_stm:
+ /* empty */ {[]}
+| stm_dots plus_after_dots { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
+| fundecl plus_after_stm { Ast0.wrap(Ast0.DECL($1))::$2 }
+| decl_statement plus_after_stm
+ { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
+
+/* ------------------------------------------------------------------------ */
+/* Function body */
+
+fun_start:
+ fun_after_stm { Ast0.wrap(Ast0.DOTS($1)) }
+
+fun_after_stm:
+ /* empty */ {[]}
+| stm_dots fun_after_dots {$1::$2}
+| decl_statement fun_after_stm {$1@$2}
+
+fun_after_dots:
+ /* empty */ {[]}
+| TNothing fun_after_exp {$2}
+| expr fun_after_exp {Ast0.wrap(Ast0.Exp($1))::$2}
+| decl_statement_expr fun_after_stm {$1@$2}
+
+fun_after_exp:
+ stm_dots fun_after_dots {$1::$2}
+
+/* hack to allow mixing statements and expressions in an or */
+fun_after_dots_or:
+ /* empty */ {[]}
+| TNothing fun_after_exp_or {$2}
+| expr fun_after_exp_or {Ast0.wrap(Ast0.Exp($1))::$2}
+| decl_statement_expr fun_after_stm {$1@$2}
+
+fun_after_exp_or:
+ /* empty */ {[]}
+| stm_dots fun_after_dots {$1::$2}
+
+/* ------------------------------------------------------------------------ */
+/* Nest body */
+
+nest_start:
+ nest_after_dots { Ast0.wrap(Ast0.DOTS($1)) }
+
+nest_after_dots:
+ decl_statement_expr nest_after_stm {$1@$2}
+| TNothing nest_after_exp {$2}
+| expr nest_after_exp {(Ast0.wrap(Ast0.Exp($1)))::$2}
+
+nest_after_stm:
+ /* empty */ {[]}
+| stm_dots nest_after_dots {$1::$2}
+| decl_statement nest_after_stm {$1@$2}
+
+nest_after_exp:
+ /* empty */ {[]}
+| stm_dots nest_after_dots {$1::$2}
+
+/* ------------------------------------------------------------------------ */
+/*Whencode*/
+
+when_start:
+ expr toplevel_after_exp
+ { Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp($1)))::$2)) }
+| decl_statement toplevel_after_stm
+ { Ast0.wrap(Ast0.DOTS($1@$2)) }
+
+/* ---------------------------------------------------------------------- */
+
+eexpr_list:
+ eexpr_list_start
+ {let circle x =
+ match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
+ let star x =
+ match Ast0.unwrap x with Ast0.Estars(_) -> true | _ -> false in
+ if List.exists circle $1
+ then Ast0.wrap(Ast0.CIRCLES($1))
+ else
+ if List.exists star $1
+ then Ast0.wrap(Ast0.STARS($1))
+ else Ast0.wrap(Ast0.DOTS($1)) }
+
+/* arg expr. may contain a type or a explist metavariable */
+aexpr:
+ eexpr
+ { Ast0.set_arg_exp $1 }
+ | TMetaExpList
+ { let (nm,lenname,pure,clt) = $1 in
+ let nm = P.clt2mcode nm clt in
+ let lenname =
+ match lenname with
+ Some nm -> Some(P.clt2mcode nm clt)
+ | None -> None in
+ Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) }
+ | ctype
+ { Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp($1))) }
+
+eexpr_list_start:
+ aexpr { [$1] }
+ | aexpr TComma eexpr_list_start
+ { $1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," $2))::$3 }
+
+comma_args(dotter):
+ c=TComma d=dotter
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.EComma(P.clt2mcode "," c)); dot_builder d] }
+| TComma aexpr
+ { function dot_builder ->
+ [Ast0.wrap(Ast0.EComma(P.clt2mcode "," $1)); $2] }
+
+eexpr_list_option: eexpr_list { $1 }
+ | /* empty */ { Ast0.wrap(Ast0.DOTS([])) }
+
+/****************************************************************************/
+
+// non-empty lists - drop separator
+comma_list(elem):
+ separated_nonempty_list(TComma,elem) { $1 }
+
+midzero_list(elem,aft):
+ a=elem b=list(mzl(aft))
+ { let (mids,code) = List.split b in (mids,(a::code)) }
+
+mzl(elem):
+ a=TMid0 b=elem { (P.clt2mcode "|" a, b) }
+
+edots_when(dotter,when_grammar):
+ d=dotter { (d,None) }
+ | d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
+
+whens(when_grammar,simple_when_grammar):
+ TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
+ | TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
+ | TWhen comma_list(any_strict) TLineEnd
+ { List.map (function x -> Ast0.WhenModifier(x)) $2 }
+ | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
+ | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
+
+any_strict:
+ TAny { Ast.WhenAny }
+ | TStrict { Ast.WhenStrict }
+ | TForall { Ast.WhenForall }
+ | TExists { Ast.WhenExists }
+
+/*****************************************************************************
+*
+*
+*****************************************************************************/
+
+iso_main:
+ TIsoExpression e1=dexpr el=list(iso(dexpr)) EOF
+ { P.iso_adjust (function x -> Ast0.ExprTag x) e1 el }
+| TIsoArgExpression e1=dexpr el=list(iso(dexpr)) EOF
+ { P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el }
+| TIsoTestExpression e1=dexpr el=list(iso(dexpr)) EOF
+ { P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el }
+| TIsoStatement s1=single_statement sl=list(iso(single_statement)) EOF
+ { P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl }
+| TIsoType t1=ctype tl=list(iso(ctype)) EOF
+ { P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl }
+| TIsoTopLevel e1=nest_start el=list(iso(nest_start)) EOF
+ { P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el }
+| TIsoDeclaration d1=decl_var dl=list(iso(decl_var)) EOF
+ { let check_one = function
+ [x] -> x
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ "only one variable per declaration in an isomorphism rule") in
+ let d1 = check_one d1 in
+ let dl =
+ List.map
+ (function
+ Common.Left x -> Common.Left(check_one x)
+ | Common.Right x -> Common.Right(check_one x))
+ dl in
+ P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl }
+
+iso(term):
+ TIso t=term { Common.Left t }
+ | TRightIso t=term { Common.Right t }
+
+/*****************************************************************************
+*
+*
+*****************************************************************************/
+
+never_used: TPragma { () }
+ | TPArob TMetaPos { () }
+ | TScriptData { () }
+
+script_meta_main: py=pure_ident TShOp TRuleName TDot cocci=pure_ident TMPtVirg
+ { (P.id2name py, ($3, P.id2name cocci)) }
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Format
+module Ast = Ast_cocci
+
+let print_plus_flag = ref true
+let print_minus_flag = ref true
+let print_newlines_disj = ref true
+
+let start_block str =
+ force_newline(); print_string " "; open_box 0
+
+let end_block str =
+ close_box(); force_newline ()
+
+let print_string_box s = print_string s; open_box 0
+
+
+let print_option = Common.do_option
+let print_between = Common.print_between
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+(* avoid polyvariance problems *)
+let anything : (Ast.anything -> unit) ref = ref (function _ -> ())
+
+let rec print_anything str = function
+ [] -> ()
+ | stream ->
+ start_block();
+ print_between force_newline
+ (function x ->
+ print_string str; open_box 0; print_anything_list x; close_box())
+ stream;
+ end_block()
+
+and print_anything_list = function
+ [] -> ()
+ | [x] -> !anything x
+ | bef::((aft::_) as rest) ->
+ !anything bef;
+ let space =
+ (match bef with
+ Ast.Rule_elemTag(_) | Ast.AssignOpTag(_) | Ast.BinaryOpTag(_)
+ | Ast.ArithOpTag(_) | Ast.LogicalOpTag(_)
+ | Ast.Token("if",_) | Ast.Token("while",_) -> true | _ -> false) or
+ (match aft with
+ Ast.Rule_elemTag(_) | Ast.AssignOpTag(_) | Ast.BinaryOpTag(_)
+ | Ast.ArithOpTag(_) | Ast.LogicalOpTag(_) | Ast.Token("{",_) -> true
+ | _ -> false) in
+ if space then print_string " ";
+ print_anything_list rest
+
+let print_around printer term = function
+ Ast.NOTHING -> printer term
+ | Ast.BEFORE(bef) -> print_anything "<<< " bef; printer term
+ | Ast.AFTER(aft) -> printer term; print_anything ">>> " aft
+ | Ast.BEFOREAFTER(bef,aft) ->
+ print_anything "<<< " bef; printer term; print_anything ">>> " aft
+
+let print_string_befaft fn x info =
+ List.iter (function s -> print_string s; force_newline())
+ info.Ast.strbef;
+ fn x;
+ List.iter (function s -> force_newline(); print_string s)
+ info.Ast.straft
+
+let print_meta (r,x) = print_string r; print_string ":"; print_string x
+
+let print_pos = function
+ Ast.MetaPos(name,_,_,_,_) ->
+ let name = Ast.unwrap_mcode name in
+ print_string "@"; print_meta name
+ | _ -> ()
+
+let mcode fn = function
+ (x, _, Ast.MINUS(_,plus_stream), pos) ->
+ if !print_minus_flag
+ then print_string (if !Flag.sgrep_mode2 then "*" else "-");
+ fn x; print_pos pos;
+ if !print_plus_flag
+ then print_anything ">>> " plus_stream
+ | (x, _, Ast.CONTEXT(_,plus_streams), pos) ->
+ if !print_plus_flag
+ then
+ let fn x = fn x; print_pos pos in
+ print_around fn x plus_streams
+ else (fn x; print_pos pos)
+ | (x, info, Ast.PLUS, pos) ->
+ let fn x = fn x; print_pos pos in
+ print_string_befaft fn x info
+
+let print_mcodekind = function
+ Ast.MINUS(_,plus_stream) ->
+ print_string "MINUS";
+ print_anything ">>> " plus_stream
+ | Ast.CONTEXT(_,plus_streams) ->
+ print_around (function _ -> print_string "CONTEXT") () plus_streams
+ | Ast.PLUS -> print_string "PLUS"
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots between fn d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) -> print_between between fn l
+ | Ast.CIRCLES(l) -> print_between between fn l
+ | Ast.STARS(l) -> print_between between fn l
+
+let nest_dots multi fn f d =
+ let mo s = if multi then "<+"^s else "<"^s in
+ let mc s = if multi then s^"+>" else s^">" in
+ match Ast.unwrap d with
+ Ast.DOTS(l) ->
+ print_string (mo "..."); f(); start_block();
+ print_between force_newline fn l;
+ end_block(); print_string (mc "...")
+ | Ast.CIRCLES(l) ->
+ print_string (mo "ooo"); f(); start_block();
+ print_between force_newline fn l;
+ end_block(); print_string (mc "ooo")
+ | Ast.STARS(l) ->
+ print_string (mo "***"); f(); start_block();
+ print_between force_newline fn l;
+ end_block(); print_string (mc "***")
+
+(* --------------------------------------------------------------------- *)
+
+let print_type keep info = function
+ None -> ()
+ (* print_string "/* ";
+ print_string "keep:"; print_unitary keep;
+ print_string " inherited:"; print_bool inherited;
+ print_string " */"*)
+ | Some ty -> ()
+ (*;
+ print_string "/* ";
+ print_between (function _ -> print_string ", ") Type_cocci.typeC ty;(*
+ print_string "keep:"; print_unitary keep;
+ print_string " inherited:"; print_bool inherited;*)
+ print_string " */"*)
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let rec ident i =
+ match Ast.unwrap i with
+ Ast.Id(name) -> mcode print_string name
+ | Ast.MetaId(name,_,keep,inherited) -> mcode print_meta name
+ | Ast.MetaFunc(name,_,_,_) -> mcode print_meta name
+ | Ast.MetaLocalFunc(name,_,_,_) -> mcode print_meta name
+ | Ast.OptIdent(id) -> print_string "?"; ident id
+ | Ast.UniqueIdent(id) -> print_string "!"; ident id
+
+and print_unitary = function
+ Type_cocci.Unitary -> print_string "unitary"
+ | Type_cocci.Nonunitary -> print_string "nonunitary"
+ | Type_cocci.Saved -> print_string "saved"
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let print_disj_list fn l =
+ if !print_newlines_disj
+ then (force_newline(); print_string "("; force_newline())
+ else print_string "(";
+ print_between
+ (function _ ->
+ if !print_newlines_disj
+ then (force_newline(); print_string "|"; force_newline())
+ else print_string " | ")
+ fn l;
+ if !print_newlines_disj
+ then (force_newline(); print_string ")"; force_newline())
+ else print_string ")"
+
+let rec expression e =
+ match Ast.unwrap e with
+ Ast.Ident(id) -> ident id
+ | Ast.Constant(const) -> mcode constant const
+ | Ast.FunCall(fn,lp,args,rp) ->
+ expression fn; mcode print_string_box lp;
+ dots (function _ -> ()) expression args;
+ close_box(); mcode print_string rp
+ | Ast.Assignment(left,op,right,simple) ->
+ expression left; print_string " "; mcode assignOp op;
+ print_string " "; expression right
+ | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
+ expression exp1; print_string " "; mcode print_string why;
+ print_option (function e -> print_string " "; expression e) exp2;
+ print_string " "; mcode print_string colon; expression exp3
+ | Ast.Postfix(exp,op) -> expression exp; mcode fixOp op
+ | Ast.Infix(exp,op) -> mcode fixOp op; expression exp
+ | Ast.Unary(exp,op) -> mcode unaryOp op; expression exp
+ | Ast.Binary(left,op,right) ->
+ expression left; print_string " "; mcode binaryOp op; print_string " ";
+ expression right
+ | Ast.Nested(left,op,right) ->
+ expression left; print_string " "; mcode binaryOp op; print_string " ";
+ expression right
+ | Ast.Paren(lp,exp,rp) ->
+ mcode print_string_box lp; expression exp; close_box();
+ mcode print_string rp
+ | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
+ expression exp1; mcode print_string_box lb; expression exp2; close_box();
+ mcode print_string rb
+ | Ast.RecordAccess(exp,pt,field) ->
+ expression exp; mcode print_string pt; ident field
+ | Ast.RecordPtAccess(exp,ar,field) ->
+ expression exp; mcode print_string ar; ident field
+ | Ast.Cast(lp,ty,rp,exp) ->
+ mcode print_string_box lp; fullType ty; close_box();
+ mcode print_string rp; expression exp
+ | Ast.SizeOfExpr(sizeof,exp) ->
+ mcode print_string sizeof; expression exp
+ | Ast.SizeOfType(sizeof,lp,ty,rp) ->
+ mcode print_string sizeof;
+ mcode print_string_box lp; fullType ty; close_box();
+ mcode print_string rp
+ | Ast.TypeExp(ty) -> fullType ty
+
+ | Ast.MetaErr(name,_,_,_) -> mcode print_meta name
+ | Ast.MetaExpr(name,_,keep,ty,form,inherited) ->
+ mcode print_meta name; print_type keep inherited ty
+ | Ast.MetaExprList(name,_,_,_) -> mcode print_meta name
+ | Ast.EComma(cm) -> mcode print_string cm; print_space()
+ | Ast.DisjExpr(exp_list) -> print_disj_list expression exp_list
+ | Ast.NestExpr(expr_dots,Some whencode,multi) ->
+ nest_dots multi expression
+ (function _ -> print_string " when != "; expression whencode)
+ expr_dots
+ | Ast.NestExpr(expr_dots,None,multi) ->
+ nest_dots multi expression (function _ -> ()) expr_dots
+ | Ast.Edots(dots,Some whencode)
+ | Ast.Ecircles(dots,Some whencode)
+ | Ast.Estars(dots,Some whencode) ->
+ mcode print_string dots; print_string " when != "; expression whencode
+ | Ast.Edots(dots,None)
+ | Ast.Ecircles(dots,None)
+ | Ast.Estars(dots,None) -> mcode print_string dots
+ | Ast.OptExp(exp) -> print_string "?"; expression exp
+ | Ast.UniqueExp(exp) -> print_string "!"; expression exp
+
+and unaryOp = function
+ Ast.GetRef -> print_string "&"
+ | Ast.DeRef -> print_string "*"
+ | Ast.UnPlus -> print_string "+"
+ | Ast.UnMinus -> print_string "-"
+ | Ast.Tilde -> print_string "~"
+ | Ast.Not -> print_string "!"
+
+and assignOp = function
+ Ast.SimpleAssign -> print_string "="
+ | Ast.OpAssign(aop) -> arithOp aop; print_string "="
+
+and fixOp = function
+ Ast.Dec -> print_string "--"
+ | Ast.Inc -> print_string "++"
+
+and binaryOp = function
+ Ast.Arith(aop) -> arithOp aop
+ | Ast.Logical(lop) -> logicalOp lop
+
+and arithOp = function
+ Ast.Plus -> print_string "+"
+ | Ast.Minus -> print_string "-"
+ | Ast.Mul -> print_string "*"
+ | Ast.Div -> print_string "/"
+ | Ast.Mod -> print_string "%"
+ | Ast.DecLeft -> print_string "<<"
+ | Ast.DecRight -> print_string ">>"
+ | Ast.And -> print_string "&"
+ | Ast.Or -> print_string "|"
+ | Ast.Xor -> print_string "^"
+
+and logicalOp = function
+ Ast.Inf -> print_string "<"
+ | Ast.Sup -> print_string ">"
+ | Ast.InfEq -> print_string "<="
+ | Ast.SupEq -> print_string ">="
+ | Ast.Eq -> print_string "=="
+ | Ast.NotEq -> print_string "!="
+ | Ast.AndLog -> print_string "&&"
+ | Ast.OrLog -> print_string "||"
+
+and constant = function
+ Ast.String(s) -> print_string "\""; print_string s; print_string "\""
+ | Ast.Char(s) -> print_string "'"; print_string s; print_string "'"
+ | Ast.Int(s) -> print_string s
+ | Ast.Float(s) -> print_string s
+
+(* --------------------------------------------------------------------- *)
+(* Declarations *)
+
+and storage = function
+ Ast.Static -> print_string "static "
+ | Ast.Auto -> print_string "auto "
+ | Ast.Register -> print_string "register "
+ | Ast.Extern -> print_string "extern "
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and fullType ft =
+ match Ast.unwrap ft with
+ Ast.Type(cv,ty) ->
+ print_option (function x -> mcode const_vol x; print_string " ") cv;
+ typeC ty
+ | Ast.DisjType(decls) -> print_disj_list fullType decls
+ | Ast.OptType(ty) -> print_string "?"; fullType ty
+ | Ast.UniqueType(ty) -> print_string "!"; fullType ty
+
+and print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2) fn =
+ fullType ty; mcode print_string lp1; mcode print_string star; fn();
+ mcode print_string rp1; mcode print_string lp1;
+ parameter_list params; mcode print_string rp2
+
+and print_function_type (ty,lp1,params,rp1) fn =
+ print_option fullType ty; fn(); mcode print_string lp1;
+ parameter_list params; mcode print_string rp1
+
+and print_fninfo = function
+ Ast.FStorage(stg) -> mcode storage stg
+ | Ast.FType(ty) -> fullType ty
+ | Ast.FInline(inline) -> mcode print_string inline; print_string " "
+ | Ast.FAttr(attr) -> mcode print_string attr; print_string " "
+
+and typeC ty =
+ match Ast.unwrap ty with
+ Ast.BaseType(ty,sgn) -> print_option (mcode sign) sgn; mcode baseType ty
+ | Ast.ImplicitInt(sgn) -> mcode sign sgn
+ | Ast.Pointer(ty,star) -> fullType ty; mcode print_string star
+ | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> ())
+ | Ast.FunctionType (_,ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1) (function _ -> ())
+ | Ast.Array(ty,lb,size,rb) ->
+ fullType ty; mcode print_string lb; print_option expression size;
+ mcode print_string rb
+ | Ast.StructUnionName(kind,name) ->
+ mcode structUnion kind;
+ print_option (function x -> ident x; print_string " ") name
+ | Ast.StructUnionDef(ty,lb,decls,rb) ->
+ fullType ty; mcode print_string lb;
+ dots force_newline declaration decls;
+ mcode print_string rb
+ | Ast.TypeName(name) -> mcode print_string name; print_string " "
+ | Ast.MetaType(name,_,_) ->
+ mcode print_meta name; print_string " "
+
+and baseType = function
+ Ast.VoidType -> print_string "void "
+ | Ast.CharType -> print_string "char "
+ | Ast.ShortType -> print_string "short "
+ | Ast.IntType -> print_string "int "
+ | Ast.DoubleType -> print_string "double "
+ | Ast.FloatType -> print_string "float "
+ | Ast.LongType -> print_string "long "
+
+and structUnion = function
+ Ast.Struct -> print_string "struct "
+ | Ast.Union -> print_string "union "
+
+and sign = function
+ Ast.Signed -> print_string "signed "
+ | Ast.Unsigned -> print_string "unsigned "
+
+and const_vol = function
+ Ast.Const -> print_string "const"
+ | Ast.Volatile -> print_string "volatile"
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and print_named_type ty id =
+ match Ast.unwrap ty with
+ Ast.Type(None,ty1) ->
+ (match Ast.unwrap ty1 with
+ Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> print_string " "; ident id)
+ | Ast.FunctionType(_,ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1)
+ (function _ -> print_string " "; ident id)
+ | Ast.Array(ty,lb,size,rb) ->
+ let rec loop ty k =
+ match Ast.unwrap ty with
+ Ast.Array(ty,lb,size,rb) ->
+ (match Ast.unwrap ty with
+ Ast.Type(None,ty) ->
+ loop ty
+ (function _ ->
+ k ();
+ mcode print_string lb;
+ print_option expression size;
+ mcode print_string rb)
+ | _ -> failwith "complex array types not supported")
+ | _ -> typeC ty; ident id; k () in
+ loop ty1 (function _ -> ())
+ | _ -> fullType ty; ident id)
+ | _ -> fullType ty; ident id
+
+and declaration d =
+ match Ast.unwrap d with
+ Ast.Init(stg,ty,id,eq,ini,sem) ->
+ print_option (mcode storage) stg; print_named_type ty id;
+ print_string " "; mcode print_string eq;
+ print_string " "; initialiser ini; mcode print_string sem
+ | Ast.UnInit(stg,ty,id,sem) ->
+ print_option (mcode storage) stg; print_named_type ty id;
+ mcode print_string sem
+ | Ast.MacroDecl(name,lp,args,rp,sem) ->
+ ident name; mcode print_string_box lp;
+ dots (function _ -> ()) expression args;
+ close_box(); mcode print_string rp; mcode print_string sem
+ | Ast.TyDecl(ty,sem) -> fullType ty; mcode print_string sem
+ | Ast.Typedef(stg,ty,id,sem) ->
+ mcode print_string stg; print_string " "; fullType ty; typeC id;
+ mcode print_string sem
+ | Ast.DisjDecl(decls) -> print_disj_list declaration decls
+ | Ast.Ddots(dots,Some whencode) ->
+ mcode print_string dots; print_string " when != "; declaration whencode
+ | Ast.Ddots(dots,None) -> mcode print_string dots
+ | Ast.MetaDecl(name,_,_) -> mcode print_meta name
+ | Ast.OptDecl(decl) -> print_string "?"; declaration decl
+ | Ast.UniqueDecl(decl) -> print_string "!"; declaration decl
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and initialiser i =
+ match Ast.unwrap i with
+ Ast.InitExpr(exp) -> expression exp
+ | Ast.InitList(lb,initlist,rb,whencode) ->
+ mcode print_string lb; open_box 0;
+ if not (whencode = [])
+ then
+ (print_string " WHEN != ";
+ print_between (function _ -> print_string " v ")
+ initialiser whencode;
+ force_newline());
+ List.iter initialiser initlist; close_box();
+ mcode print_string rb
+ | Ast.InitGccDotName(dot,name,eq,ini) ->
+ mcode print_string dot; ident name; print_string " ";
+ mcode print_string eq; print_string " "; initialiser ini
+ | Ast.InitGccName(name,eq,ini) ->
+ ident name; mcode print_string eq; initialiser ini
+ | Ast.InitGccIndex(lb,exp,rb,eq,ini) ->
+ mcode print_string lb; expression exp; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ mcode print_string lb; expression exp1; mcode print_string dots;
+ expression exp2; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast.IComma(comma) -> mcode print_string comma; force_newline()
+ | Ast.OptIni(ini) -> print_string "?"; initialiser ini
+ | Ast.UniqueIni(ini) -> print_string "!"; initialiser ini
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef p =
+ match Ast.unwrap p with
+ Ast.VoidParam(ty) -> fullType ty
+ | Ast.Param(ty,Some id) -> print_named_type ty id
+ | Ast.Param(ty,None) -> fullType ty
+ | Ast.MetaParam(name,_,_) -> mcode print_meta name
+ | Ast.MetaParamList(name,_,_,_) -> mcode print_meta name
+ | Ast.PComma(cm) -> mcode print_string cm; print_space()
+ | Ast.Pdots(dots) -> mcode print_string dots
+ | Ast.Pcircles(dots) -> mcode print_string dots
+ | Ast.OptParam(param) -> print_string "?"; parameterTypeDef param
+ | Ast.UniqueParam(param) -> print_string "!"; parameterTypeDef param
+
+and parameter_list l = dots (function _ -> ()) parameterTypeDef l
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+let rec rule_elem arity re =
+ match Ast.unwrap re with
+ Ast.FunHeader(bef,allminus,fninfo,name,lp,params,rp) ->
+ mcode (function _ -> ()) ((),Ast.no_info,bef,Ast.NoMetaPos);
+ print_string arity; List.iter print_fninfo fninfo;
+ ident name; mcode print_string_box lp;
+ parameter_list params; close_box(); mcode print_string rp;
+ print_string " "
+ | Ast.Decl(bef,allminus,decl) ->
+ mcode (function _ -> ()) ((),Ast.no_info,bef,Ast.NoMetaPos);
+ print_string arity;
+ declaration decl
+ | Ast.SeqStart(brace) ->
+ print_string arity; mcode print_string brace;
+ if !print_newlines_disj then start_block()
+ | Ast.SeqEnd(brace) ->
+ if !print_newlines_disj then end_block();
+ print_string arity; mcode print_string brace
+ | Ast.ExprStatement(exp,sem) ->
+ print_string arity; expression exp; mcode print_string sem
+ | Ast.IfHeader(iff,lp,exp,rp) ->
+ print_string arity;
+ mcode print_string iff; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " "
+ | Ast.Else(els) ->
+ print_string arity; mcode print_string els; print_string " "
+ | Ast.WhileHeader(whl,lp,exp,rp) ->
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " "
+ | Ast.DoHeader(d) ->
+ print_string arity; mcode print_string d; print_string " "
+ | Ast.WhileTail(whl,lp,exp,rp,sem) ->
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp;
+ mcode print_string sem
+ | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
+ print_string arity;
+ mcode print_string fr; mcode print_string_box lp;
+ print_option expression e1; mcode print_string sem1;
+ print_option expression e2; mcode print_string sem2;
+ print_option expression e3; close_box();
+ mcode print_string rp; print_string " "
+ | Ast.IteratorHeader(nm,lp,args,rp) ->
+ print_string arity;
+ ident nm; print_string " "; mcode print_string_box lp;
+ dots (function _ -> ()) expression args; close_box();
+ mcode print_string rp; print_string " "
+ | Ast.SwitchHeader(switch,lp,exp,rp) ->
+ print_string arity;
+ mcode print_string switch; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " "
+ | Ast.Break(br,sem) ->
+ print_string arity; mcode print_string br; mcode print_string sem
+ | Ast.Continue(cont,sem) ->
+ print_string arity; mcode print_string cont; mcode print_string sem
+ | Ast.Label(l,dd) -> ident l; mcode print_string dd
+ | Ast.Goto(goto,l,sem) ->
+ mcode print_string goto; ident l; mcode print_string sem
+ | Ast.Return(ret,sem) ->
+ print_string arity; mcode print_string ret; mcode print_string sem
+ | Ast.ReturnExpr(ret,exp,sem) ->
+ print_string arity; mcode print_string ret; print_string " ";
+ expression exp; mcode print_string sem
+ | Ast.MetaRuleElem(name,_,_) ->
+ print_string arity; mcode print_meta name
+ | Ast.MetaStmt(name,_,_,_) ->
+ print_string arity; mcode print_meta name
+ | Ast.MetaStmtList(name,_,_) ->
+ print_string arity; mcode print_meta name
+ | Ast.Exp(exp) -> print_string arity; expression exp
+ | Ast.TopExp(exp) -> print_string arity; expression exp
+ | Ast.Ty(ty) -> print_string arity; fullType ty
+ | Ast.Include(inc,s) ->
+ mcode print_string inc; print_string " "; mcode inc_file s
+ | Ast.DefineHeader(def,id,params) ->
+ mcode print_string def; print_string " "; ident id;
+ print_define_parameters params
+ | Ast.Default(def,colon) ->
+ mcode print_string def; mcode print_string colon; print_string " "
+ | Ast.Case(case,exp,colon) ->
+ mcode print_string case; print_string " "; expression exp;
+ mcode print_string colon; print_string " "
+ | Ast.DisjRuleElem(res) ->
+ print_string arity;
+ force_newline(); print_string "("; force_newline();
+ print_between
+ (function _ -> force_newline();print_string "|"; force_newline())
+ (rule_elem arity)
+ res;
+ force_newline(); print_string ")"
+
+
+and print_define_parameters params =
+ match Ast.unwrap params with
+ Ast.NoParams -> ()
+ | Ast.DParams(lp,params,rp) ->
+ mcode print_string lp;
+ dots (function _ -> ()) print_define_param params; mcode print_string rp
+
+and print_define_param param =
+ match Ast.unwrap param with
+ Ast.DParam(id) -> ident id
+ | Ast.DPComma(comma) -> mcode print_string comma
+ | Ast.DPdots(dots) -> mcode print_string dots
+ | Ast.DPcircles(circles) -> mcode print_string circles
+ | Ast.OptDParam(dp) -> print_string "?"; print_define_param dp
+ | Ast.UniqueDParam(dp) -> print_string "!"; print_define_param dp
+
+and statement arity s =
+ match Ast.unwrap s with
+ Ast.Seq(lbrace,decls,body,rbrace) ->
+ rule_elem arity lbrace;
+ dots force_newline (statement arity) decls;
+ dots force_newline (statement arity) body;
+ rule_elem arity rbrace
+ | Ast.IfThen(header,branch,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity branch;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.IfThenElse(header,branch1,els,branch2,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity branch1; print_string " ";
+ rule_elem arity els; statement arity branch2;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.While(header,body,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity body;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.Do(header,body,tail) ->
+ rule_elem arity header; statement arity body;
+ rule_elem arity tail
+ | Ast.For(header,body,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity body;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.Iterator(header,body,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity body;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.Switch(header,lb,cases,rb) ->
+ rule_elem arity header; rule_elem arity lb;
+ List.iter (function x -> case_line arity x; force_newline()) cases;
+ rule_elem arity rb
+ | Ast.Atomic(re) -> rule_elem arity re
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ rule_elem arity header; rule_elem arity lbrace;
+ dots force_newline (statement arity) decls;
+ dots force_newline (statement arity) body;
+ rule_elem arity rbrace
+ | Ast.Disj([stmt_dots]) ->
+ print_string arity;
+ dots (function _ -> if !print_newlines_disj then force_newline())
+ (statement arity) stmt_dots
+ | Ast.Disj(stmt_dots_list) -> (* ignores newline directive for readability *)
+ print_string arity;
+ force_newline(); print_string "("; force_newline();
+ print_between
+ (function _ -> force_newline();print_string "|"; force_newline())
+ (dots force_newline (statement arity))
+ stmt_dots_list;
+ force_newline(); print_string ")"
+ | Ast.Define(header,body) ->
+ rule_elem arity header; print_string " ";
+ dots force_newline (statement arity) body
+ | Ast.Nest(stmt_dots,whn,multi,_,_) ->
+ print_string arity;
+ nest_dots multi (statement arity)
+ (function _ ->
+ open_box 0;
+ print_between force_newline
+ (whencode (dots force_newline (statement "")) (statement "")) whn;
+ close_box(); force_newline())
+ stmt_dots
+ | Ast.Dots(d,whn,_,_) | Ast.Circles(d,whn,_,_) | Ast.Stars(d,whn,_,_) ->
+ print_string arity; mcode print_string d;
+ open_box 0;
+ print_between force_newline
+ (whencode (dots force_newline (statement "")) (statement "")) whn;
+ close_box(); force_newline()
+ | Ast.OptStm(s) -> statement "?" s
+ | Ast.UniqueStm(s) -> statement "!" s
+
+and print_statement_when whencode =
+ print_string " WHEN != ";
+ open_box 0;
+ print_between (function _ -> print_string " &"; force_newline())
+ (dots force_newline (statement "")) whencode;
+ close_box()
+
+
+and whencode notfn alwaysfn = function
+ Ast.WhenNot a ->
+ print_string " WHEN != "; open_box 0; notfn a; close_box()
+ | Ast.WhenAlways a ->
+ print_string " WHEN = "; open_box 0; alwaysfn a; close_box()
+ | Ast.WhenModifier x -> print_string " WHEN "; print_when_modif x
+
+and print_when_modif = function
+ | Ast.WhenAny -> print_string "ANY"
+ | Ast.WhenStrict -> print_string "STRICT"
+ | Ast.WhenForall -> print_string "FORALL"
+ | Ast.WhenExists -> print_string "EXISTS"
+
+and case_line arity c =
+ match Ast.unwrap c with
+ Ast.CaseLine(header,code) ->
+ rule_elem arity header; print_string " ";
+ dots force_newline (statement arity) code
+ | Ast.OptCase(case) -> case_line "?" case
+
+(* --------------------------------------------------------------------- *)
+(* CPP code *)
+
+and inc_file = function
+ Ast.Local(elems) ->
+ print_string "\"";
+ print_between (function _ -> print_string "/") inc_elem elems;
+ print_string "\""
+ | Ast.NonLocal(elems) ->
+ print_string "<";
+ print_between (function _ -> print_string "/") inc_elem elems;
+ print_string ">"
+
+and inc_elem = function
+ Ast.IncPath s -> print_string s
+ | Ast.IncDots -> print_string "..."
+
+(* for export only *)
+let statement_dots l = dots force_newline (statement "") l
+
+let top_level t =
+ match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) ->
+ print_string "--- "; mcode print_string old_file; force_newline();
+ print_string "+++ "; mcode print_string new_file
+ | Ast.DECL(stmt) -> statement "" stmt
+ | Ast.CODE(stmt_dots) ->
+ dots force_newline (statement "") stmt_dots
+ | Ast.ERRORWORDS(exps) ->
+ print_string "error words = [";
+ print_between (function _ -> print_string ", ") expression exps;
+ print_string "]"
+
+let rule =
+ print_between (function _ -> force_newline(); force_newline()) top_level
+
+let pp_print_anything x = !anything x
+
+let _ =
+ anything := function
+ Ast.FullTypeTag(x) -> fullType x
+ | Ast.BaseTypeTag(x) -> baseType x
+ | Ast.StructUnionTag(x) -> structUnion x
+ | Ast.SignTag(x) -> sign x
+ | Ast.IdentTag(x) -> ident x
+ | Ast.ExpressionTag(x) -> expression x
+ | Ast.ConstantTag(x) -> constant x
+ | Ast.UnaryOpTag(x) -> unaryOp x
+ | Ast.AssignOpTag(x) -> assignOp x
+ | Ast.FixOpTag(x) -> fixOp x
+ | Ast.BinaryOpTag(x) -> binaryOp x
+ | Ast.ArithOpTag(x) -> arithOp x
+ | Ast.LogicalOpTag(x) -> logicalOp x
+ | Ast.InitTag(x) -> initialiser x
+ | Ast.DeclarationTag(x) -> declaration x
+ | Ast.StorageTag(x) -> storage x
+ | Ast.IncFileTag(x) -> inc_file x
+ | Ast.Rule_elemTag(x) -> rule_elem "" x
+ | Ast.StatementTag(x) -> statement "" x
+ | Ast.CaseLineTag(x) -> case_line "" x
+ | Ast.ConstVolTag(x) -> const_vol x
+ | Ast.Token(x,Some info) -> print_string_befaft print_string x info
+ | Ast.Token(x,None) -> print_string x
+ | Ast.Code(x) -> let _ = top_level x in ()
+ | Ast.ExprDotsTag(x) -> dots (function _ -> ()) expression x
+ | Ast.ParamDotsTag(x) -> parameter_list x
+ | Ast.StmtDotsTag(x) -> dots (function _ -> ()) (statement "") x
+ | Ast.DeclDotsTag(x) -> dots (function _ -> ()) declaration x
+ | Ast.TypeCTag(x) -> typeC x
+ | Ast.ParamTag(x) -> parameterTypeDef x
+ | Ast.SgrepStartTag(x) -> print_string x
+ | Ast.SgrepEndTag(x) -> print_string x
+
+let rec dep in_and = function
+ Ast.Dep(s) -> print_string s
+ | Ast.AntiDep(s) -> print_string "!"; print_string s
+ | Ast.EverDep(s) -> print_string "ever "; print_string s
+ | Ast.NeverDep(s) -> print_string "never "; print_string s
+ | Ast.AndDep(s1,s2) ->
+ let print_and _ = dep true s1; print_string " && "; dep true s2 in
+ if in_and
+ then print_and ()
+ else (print_string "("; print_and(); print_string ")")
+ | Ast.OrDep(s1,s2) ->
+ let print_or _ = dep false s1; print_string " || "; dep false s2 in
+ if not in_and
+ then print_or ()
+ else (print_string "("; print_or(); print_string ")")
+ | Ast.NoDep -> failwith "not possible"
+
+let unparse z =
+ match z with
+ Ast.ScriptRule (lang,deps,bindings,code) ->
+ print_string "@@";
+ force_newline();
+ print_string ("script:" ^ lang);
+ (match deps with
+ Ast.NoDep -> ()
+ | _ -> print_string " depends on "; dep true deps);
+ force_newline();
+ print_string "@@";
+ force_newline();
+ print_string code;
+ force_newline()
+ | Ast.CocciRule (nm, (deps, drops, exists), x, _) ->
+ print_string "@@";
+ force_newline();
+ print_string nm;
+ (match deps with
+ Ast.NoDep -> ()
+ | _ -> print_string " depends on "; dep true deps);
+ (*
+ print_string "line ";
+ print_int (Ast.get_line (List.hd x));
+ *)
+ force_newline();
+ print_string "@@";
+ print_newlines_disj := true;
+ force_newline();
+ force_newline();
+ rule x;
+ force_newline()
+
+let rule_elem_to_string x =
+ print_newlines_disj := true;
+ Common.format_to_string (function _ -> rule_elem "" x)
+
+let ident_to_string x =
+ print_newlines_disj := true;
+ Common.format_to_string (function _ -> ident x)
+
+let unparse_to_string x =
+ print_newlines_disj := true;
+ Common.format_to_string (function _ -> unparse x)
+
+let print_rule_elem re =
+ let nl = !print_newlines_disj in
+ print_newlines_disj := false;
+ rule_elem "" re;
+ print_newlines_disj := nl
+
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Format
+module Ast = Ast_cocci
+
+let print_plus_flag = ref true
+let print_minus_flag = ref true
+let print_newlines_disj = ref true
+
+let start_block str =
+ force_newline(); print_string " "; open_box 0
+
+let end_block str =
+ close_box(); force_newline ()
+
+let print_string_box s = print_string s; open_box 0
+
+
+let print_option = Common.do_option
+let print_between = Common.print_between
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+(* avoid polyvariance problems *)
+let anything : (Ast.anything -> unit) ref = ref (function _ -> ())
+
+let rec print_anything str = function
+ [] -> ()
+ | stream ->
+ start_block();
+ print_between force_newline
+ (function x ->
+ print_string str; open_box 0; print_anything_list x; close_box())
+ stream;
+ end_block()
+
+and print_anything_list = function
+ [] -> ()
+ | [x] -> !anything x
+ | bef::((aft::_) as rest) ->
+ !anything bef;
+ let space =
+ (match bef with
+ Ast.Rule_elemTag(_) | Ast.AssignOpTag(_) | Ast.BinaryOpTag(_)
+ | Ast.ArithOpTag(_) | Ast.LogicalOpTag(_)
+ | Ast.Token("if",_) | Ast.Token("while",_) -> true | _ -> false) or
+ (match aft with
+ Ast.Rule_elemTag(_) | Ast.AssignOpTag(_) | Ast.BinaryOpTag(_)
+ | Ast.ArithOpTag(_) | Ast.LogicalOpTag(_) | Ast.Token("{",_) -> true
+ | _ -> false) in
+ if space then print_string " ";
+ print_anything_list rest
+
+let print_around printer term = function
+ Ast.NOTHING -> printer term
+ | Ast.BEFORE(bef) -> print_anything "<<< " bef; printer term
+ | Ast.AFTER(aft) -> printer term; print_anything ">>> " aft
+ | Ast.BEFOREAFTER(bef,aft) ->
+ print_anything "<<< " bef; printer term; print_anything ">>> " aft
+
+let print_string_befaft fn x info =
+ List.iter (function s -> print_string s; force_newline())
+ info.Ast.strbef;
+ fn x;
+ List.iter (function s -> force_newline(); print_string s)
+ info.Ast.straft
+
+let print_meta (r,x) = print_string r; print_string ":"; print_string x
+
+let print_pos = function
+ Ast.MetaPos(name,_,_,_,_) ->
+ let name = Ast.unwrap_mcode name in
+ print_string "@"; print_meta name
+ | _ -> ()
+
+let mcode fn = function
+ (x, _, Ast.MINUS(_,plus_stream), pos) ->
+ if !print_minus_flag
+ then print_string (if !Flag.sgrep_mode2 then "*" else "-");
+ fn x; print_pos pos;
+ if !print_plus_flag
+ then print_anything ">>> " plus_stream
+ | (x, _, Ast.CONTEXT(_,plus_streams), pos) ->
+ if !print_plus_flag
+ then
+ let fn x = fn x; print_pos pos in
+ print_around fn x plus_streams
+ else (fn x; print_pos pos)
+ | (x, info, Ast.PLUS, pos) ->
+ let fn x = fn x; print_pos pos in
+ print_string_befaft fn x info
+
+let print_mcodekind = function
+ Ast.MINUS(_,plus_stream) ->
+ print_string "MINUS";
+ print_anything ">>> " plus_stream
+ | Ast.CONTEXT(_,plus_streams) ->
+ print_around (function _ -> print_string "CONTEXT") () plus_streams
+ | Ast.PLUS -> print_string "PLUS"
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots between fn d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) -> print_between between fn l
+ | Ast.CIRCLES(l) -> print_between between fn l
+ | Ast.STARS(l) -> print_between between fn l
+
+let nest_dots multi fn f d =
+ let mo s = if multi then "<+"^s else "<"^s in
+ let mc s = if multi then s^"+>" else s^">" in
+ match Ast.unwrap d with
+ Ast.DOTS(l) ->
+ print_string (mo "..."); f(); start_block();
+ print_between force_newline fn l;
+ end_block(); print_string (mc "...")
+ | Ast.CIRCLES(l) ->
+ print_string (mo "ooo"); f(); start_block();
+ print_between force_newline fn l;
+ end_block(); print_string (mc "ooo")
+ | Ast.STARS(l) ->
+ print_string (mo "***"); f(); start_block();
+ print_between force_newline fn l;
+ end_block(); print_string (mc "***")
+
+(* --------------------------------------------------------------------- *)
+
+let print_type keep info = function
+ None -> ()
+ (* print_string "/* ";
+ print_string "keep:"; print_unitary keep;
+ print_string " inherited:"; print_bool inherited;
+ print_string " */"*)
+ | Some ty -> ()
+ (*;
+ print_string "/* ";
+ print_between (function _ -> print_string ", ") Type_cocci.typeC ty;(*
+ print_string "keep:"; print_unitary keep;
+ print_string " inherited:"; print_bool inherited;*)
+ print_string " */"*)
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let rec ident i =
+ match Ast.unwrap i with
+ Ast.Id(name) -> mcode print_string name
+ | Ast.MetaId(name,_,keep,inherited) -> mcode print_meta name
+ | Ast.MetaFunc(name,_,_,_) -> mcode print_meta name
+ | Ast.MetaLocalFunc(name,_,_,_) -> mcode print_meta name
+ | Ast.OptIdent(id) -> print_string "?"; ident id
+ | Ast.UniqueIdent(id) -> print_string "!"; ident id
+
+and print_unitary = function
+ Type_cocci.Unitary -> print_string "unitary"
+ | Type_cocci.Nonunitary -> print_string "nonunitary"
+ | Type_cocci.Saved -> print_string "saved"
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let print_disj_list fn l =
+ if !print_newlines_disj
+ then (force_newline(); print_string "("; force_newline())
+ else print_string "(";
+ print_between
+ (function _ ->
+ if !print_newlines_disj
+ then (force_newline(); print_string "|"; force_newline())
+ else print_string " | ")
+ fn l;
+ if !print_newlines_disj
+ then (force_newline(); print_string ")"; force_newline())
+ else print_string ")"
+
+let rec expression e =
+ match Ast.unwrap e with
+ Ast.Ident(id) -> ident id
+ | Ast.Constant(const) -> mcode constant const
+ | Ast.FunCall(fn,lp,args,rp) ->
+ expression fn; mcode print_string_box lp;
+ dots (function _ -> ()) expression args;
+ close_box(); mcode print_string rp
+ | Ast.Assignment(left,op,right,simple) ->
+ expression left; print_string " "; mcode assignOp op;
+ print_string " "; expression right
+ | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
+ expression exp1; print_string " "; mcode print_string why;
+ print_option (function e -> print_string " "; expression e) exp2;
+ print_string " "; mcode print_string colon; expression exp3
+ | Ast.Postfix(exp,op) -> expression exp; mcode fixOp op
+ | Ast.Infix(exp,op) -> mcode fixOp op; expression exp
+ | Ast.Unary(exp,op) -> mcode unaryOp op; expression exp
+ | Ast.Binary(left,op,right) ->
+ expression left; print_string " "; mcode binaryOp op; print_string " ";
+ expression right
+ | Ast.Nested(left,op,right) ->
+ expression left; print_string " "; mcode binaryOp op; print_string " ";
+ expression right
+ | Ast.Paren(lp,exp,rp) ->
+ mcode print_string_box lp; expression exp; close_box();
+ mcode print_string rp
+ | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
+ expression exp1; mcode print_string_box lb; expression exp2; close_box();
+ mcode print_string rb
+ | Ast.RecordAccess(exp,pt,field) ->
+ expression exp; mcode print_string pt; ident field
+ | Ast.RecordPtAccess(exp,ar,field) ->
+ expression exp; mcode print_string ar; ident field
+ | Ast.Cast(lp,ty,rp,exp) ->
+ mcode print_string_box lp; fullType ty; close_box();
+ mcode print_string rp; expression exp
+ | Ast.SizeOfExpr(sizeof,exp) ->
+ mcode print_string sizeof; expression exp
+ | Ast.SizeOfType(sizeof,lp,ty,rp) ->
+ mcode print_string sizeof;
+ mcode print_string_box lp; fullType ty; close_box();
+ mcode print_string rp
+ | Ast.TypeExp(ty) -> fullType ty
+
+ | Ast.MetaErr(name,_,_,_) -> mcode print_meta name
+ | Ast.MetaExpr(name,_,keep,ty,form,inherited) ->
+ mcode print_meta name; print_type keep inherited ty
+ | Ast.MetaExprList(name,_,_,_) -> mcode print_meta name
+ | Ast.EComma(cm) -> mcode print_string cm; print_space()
+ | Ast.DisjExpr(exp_list) -> print_disj_list expression exp_list
+ | Ast.NestExpr(expr_dots,Some whencode,multi) ->
+ nest_dots multi expression
+ (function _ -> print_string " when != "; expression whencode)
+ expr_dots
+ | Ast.NestExpr(expr_dots,None,multi) ->
+ nest_dots multi expression (function _ -> ()) expr_dots
+ | Ast.Edots(dots,Some whencode)
+ | Ast.Ecircles(dots,Some whencode)
+ | Ast.Estars(dots,Some whencode) ->
+ mcode print_string dots; print_string " when != "; expression whencode
+ | Ast.Edots(dots,None)
+ | Ast.Ecircles(dots,None)
+ | Ast.Estars(dots,None) -> mcode print_string dots
+ | Ast.OptExp(exp) -> print_string "?"; expression exp
+ | Ast.UniqueExp(exp) -> print_string "!"; expression exp
+
+and unaryOp = function
+ Ast.GetRef -> print_string "&"
+ | Ast.DeRef -> print_string "*"
+ | Ast.UnPlus -> print_string "+"
+ | Ast.UnMinus -> print_string "-"
+ | Ast.Tilde -> print_string "~"
+ | Ast.Not -> print_string "!"
+
+and assignOp = function
+ Ast.SimpleAssign -> print_string "="
+ | Ast.OpAssign(aop) -> arithOp aop; print_string "="
+
+and fixOp = function
+ Ast.Dec -> print_string "--"
+ | Ast.Inc -> print_string "++"
+
+and binaryOp = function
+ Ast.Arith(aop) -> arithOp aop
+ | Ast.Logical(lop) -> logicalOp lop
+
+and arithOp = function
+ Ast.Plus -> print_string "+"
+ | Ast.Minus -> print_string "-"
+ | Ast.Mul -> print_string "*"
+ | Ast.Div -> print_string "/"
+ | Ast.Mod -> print_string "%"
+ | Ast.DecLeft -> print_string "<<"
+ | Ast.DecRight -> print_string ">>"
+ | Ast.And -> print_string "&"
+ | Ast.Or -> print_string "|"
+ | Ast.Xor -> print_string "^"
+
+and logicalOp = function
+ Ast.Inf -> print_string "<"
+ | Ast.Sup -> print_string ">"
+ | Ast.InfEq -> print_string "<="
+ | Ast.SupEq -> print_string ">="
+ | Ast.Eq -> print_string "=="
+ | Ast.NotEq -> print_string "!="
+ | Ast.AndLog -> print_string "&&"
+ | Ast.OrLog -> print_string "||"
+
+and constant = function
+ Ast.String(s) -> print_string "\""; print_string s; print_string "\""
+ | Ast.Char(s) -> print_string "'"; print_string s; print_string "'"
+ | Ast.Int(s) -> print_string s
+ | Ast.Float(s) -> print_string s
+
+(* --------------------------------------------------------------------- *)
+(* Declarations *)
+
+and storage = function
+ Ast.Static -> print_string "static "
+ | Ast.Auto -> print_string "auto "
+ | Ast.Register -> print_string "register "
+ | Ast.Extern -> print_string "extern "
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and fullType ft =
+ match Ast.unwrap ft with
+ Ast.Type(cv,ty) ->
+ print_option (function x -> mcode const_vol x; print_string " ") cv;
+ typeC ty
+ | Ast.DisjType(decls) -> print_disj_list fullType decls
+ | Ast.OptType(ty) -> print_string "?"; fullType ty
+ | Ast.UniqueType(ty) -> print_string "!"; fullType ty
+
+and print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2) fn =
+ fullType ty; mcode print_string lp1; mcode print_string star; fn();
+ mcode print_string rp1; mcode print_string lp1;
+ parameter_list params; mcode print_string rp2
+
+and print_function_type (ty,lp1,params,rp1) fn =
+ print_option fullType ty; fn(); mcode print_string lp1;
+ parameter_list params; mcode print_string rp1
+
+and print_fninfo = function
+ Ast.FStorage(stg) -> mcode storage stg
+ | Ast.FType(ty) -> fullType ty
+ | Ast.FInline(inline) -> mcode print_string inline; print_string " "
+ | Ast.FAttr(attr) -> mcode print_string attr; print_string " "
+
+and typeC ty =
+ match Ast.unwrap ty with
+ Ast.BaseType(ty,sgn) -> print_option (mcode sign) sgn; mcode baseType ty
+ | Ast.ImplicitInt(sgn) -> mcode sign sgn
+ | Ast.Pointer(ty,star) -> fullType ty; mcode print_string star
+ | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> ())
+ | Ast.FunctionType (_,ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1) (function _ -> ())
+ | Ast.Array(ty,lb,size,rb) ->
+ fullType ty; mcode print_string lb; print_option expression size;
+ mcode print_string rb
+ | Ast.StructUnionName(kind,name) ->
+ mcode structUnion kind;
+ print_option (function x -> ident x; print_string " ") name
+ | Ast.StructUnionDef(ty,lb,decls,rb) ->
+ fullType ty; mcode print_string lb;
+ dots force_newline declaration decls;
+ mcode print_string rb
+ | Ast.TypeName(name) -> mcode print_string name; print_string " "
+ | Ast.MetaType(name,_,_) ->
+ mcode print_meta name; print_string " "
+
+and baseType = function
+ Ast.VoidType -> print_string "void "
+ | Ast.CharType -> print_string "char "
+ | Ast.ShortType -> print_string "short "
+ | Ast.IntType -> print_string "int "
+ | Ast.DoubleType -> print_string "double "
+ | Ast.FloatType -> print_string "float "
+ | Ast.LongType -> print_string "long "
+
+and structUnion = function
+ Ast.Struct -> print_string "struct "
+ | Ast.Union -> print_string "union "
+
+and sign = function
+ Ast.Signed -> print_string "signed "
+ | Ast.Unsigned -> print_string "unsigned "
+
+and const_vol = function
+ Ast.Const -> print_string "const"
+ | Ast.Volatile -> print_string "volatile"
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and print_named_type ty id =
+ match Ast.unwrap ty with
+ Ast.Type(None,ty1) ->
+ (match Ast.unwrap ty1 with
+ Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> print_string " "; ident id)
+ | Ast.FunctionType(_,ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1)
+ (function _ -> print_string " "; ident id)
+ | Ast.Array(ty,lb,size,rb) ->
+ let rec loop ty k =
+ match Ast.unwrap ty with
+ Ast.Array(ty,lb,size,rb) ->
+ (match Ast.unwrap ty with
+ Ast.Type(None,ty) ->
+ loop ty
+ (function _ ->
+ k ();
+ mcode print_string lb;
+ print_option expression size;
+ mcode print_string rb)
+ | _ -> failwith "complex array types not supported")
+ | _ -> typeC ty; ident id; k () in
+ loop ty1 (function _ -> ())
+ | _ -> fullType ty; ident id)
+ | _ -> fullType ty; ident id
+
+and declaration d =
+ match Ast.unwrap d with
+ Ast.Init(stg,ty,id,eq,ini,sem) ->
+ print_option (mcode storage) stg; print_named_type ty id;
+ print_string " "; mcode print_string eq;
+ print_string " "; initialiser ini; mcode print_string sem
+ | Ast.UnInit(stg,ty,id,sem) ->
+ print_option (mcode storage) stg; print_named_type ty id;
+ mcode print_string sem
+ | Ast.MacroDecl(name,lp,args,rp,sem) ->
+ ident name; mcode print_string_box lp;
+ dots (function _ -> ()) expression args;
+ close_box(); mcode print_string rp; mcode print_string sem
+ | Ast.TyDecl(ty,sem) -> fullType ty; mcode print_string sem
+ | Ast.Typedef(stg,ty,id,sem) ->
+ mcode print_string stg; print_string " "; fullType ty; typeC id;
+ mcode print_string sem
+ | Ast.DisjDecl(decls) -> print_disj_list declaration decls
+ | Ast.Ddots(dots,Some whencode) ->
+ mcode print_string dots; print_string " when != "; declaration whencode
+ | Ast.Ddots(dots,None) -> mcode print_string dots
+ | Ast.MetaDecl(name,_,_) -> mcode print_meta name
+ | Ast.OptDecl(decl) -> print_string "?"; declaration decl
+ | Ast.UniqueDecl(decl) -> print_string "!"; declaration decl
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and initialiser i =
+ match Ast.unwrap i with
+ Ast.InitExpr(exp) -> expression exp
+ | Ast.InitList(lb,initlist,rb,whencode) ->
+ mcode print_string lb; open_box 0;
+ if not (whencode = [])
+ then
+ (print_string " WHEN != ";
+ print_between (function _ -> print_string " v ")
+ initialiser whencode;
+ force_newline());
+ List.iter initialiser initlist; close_box();
+ mcode print_string rb
+ | Ast.InitGccDotName(dot,name,eq,ini) ->
+ mcode print_string dot; ident name; print_string " ";
+ mcode print_string eq; print_string " "; initialiser ini
+ | Ast.InitGccName(name,eq,ini) ->
+ ident name; mcode print_string eq; initialiser ini
+ | Ast.InitGccIndex(lb,exp,rb,eq,ini) ->
+ mcode print_string lb; expression exp; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ mcode print_string lb; expression exp1; mcode print_string dots;
+ expression exp2; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast.IComma(comma) -> mcode print_string comma; force_newline()
+ | Ast.OptIni(ini) -> print_string "?"; initialiser ini
+ | Ast.UniqueIni(ini) -> print_string "!"; initialiser ini
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef p =
+ match Ast.unwrap p with
+ Ast.VoidParam(ty) -> fullType ty
+ | Ast.Param(ty,Some id) -> print_named_type ty id
+ | Ast.Param(ty,None) -> fullType ty
+ | Ast.MetaParam(name,_,_) -> mcode print_meta name
+ | Ast.MetaParamList(name,_,_,_) -> mcode print_meta name
+ | Ast.PComma(cm) -> mcode print_string cm; print_space()
+ | Ast.Pdots(dots) -> mcode print_string dots
+ | Ast.Pcircles(dots) -> mcode print_string dots
+ | Ast.OptParam(param) -> print_string "?"; parameterTypeDef param
+ | Ast.UniqueParam(param) -> print_string "!"; parameterTypeDef param
+
+and parameter_list l = dots (function _ -> ()) parameterTypeDef l
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+let rec rule_elem arity re =
+ match Ast.unwrap re with
+ Ast.FunHeader(bef,allminus,fninfo,name,lp,params,rp) ->
+ mcode (function _ -> ()) ((),Ast.no_info,bef,Ast.NoMetaPos);
+ print_string arity; List.iter print_fninfo fninfo;
+ ident name; mcode print_string_box lp;
+ parameter_list params; close_box(); mcode print_string rp;
+ print_string " "
+ | Ast.Decl(bef,allminus,decl) ->
+ mcode (function _ -> ()) ((),Ast.no_info,bef,Ast.NoMetaPos);
+ print_string arity;
+ declaration decl
+ | Ast.SeqStart(brace) ->
+ print_string arity; mcode print_string brace;
+ if !print_newlines_disj then start_block()
+ | Ast.SeqEnd(brace) ->
+ if !print_newlines_disj then end_block();
+ print_string arity; mcode print_string brace
+ | Ast.ExprStatement(exp,sem) ->
+ print_string arity; expression exp; mcode print_string sem
+ | Ast.IfHeader(iff,lp,exp,rp) ->
+ print_string arity;
+ mcode print_string iff; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " "
+ | Ast.Else(els) ->
+ print_string arity; mcode print_string els; print_string " "
+ | Ast.WhileHeader(whl,lp,exp,rp) ->
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " "
+ | Ast.DoHeader(d) ->
+ print_string arity; mcode print_string d; print_string " "
+ | Ast.WhileTail(whl,lp,exp,rp,sem) ->
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp;
+ mcode print_string sem
+ | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
+ print_string arity;
+ mcode print_string fr; mcode print_string_box lp;
+ print_option expression e1; mcode print_string sem1;
+ print_option expression e2; mcode print_string sem2;
+ print_option expression e3; close_box();
+ mcode print_string rp; print_string " "
+ | Ast.IteratorHeader(nm,lp,args,rp) ->
+ print_string arity;
+ ident nm; print_string " "; mcode print_string_box lp;
+ dots (function _ -> ()) expression args; close_box();
+ mcode print_string rp; print_string " "
+ | Ast.SwitchHeader(switch,lp,exp,rp) ->
+ print_string arity;
+ mcode print_string switch; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " "
+ | Ast.Break(br,sem) ->
+ print_string arity; mcode print_string br; mcode print_string sem
+ | Ast.Continue(cont,sem) ->
+ print_string arity; mcode print_string cont; mcode print_string sem
+ | Ast.Label(l,dd) -> ident l; mcode print_string dd
+ | Ast.Goto(goto,l,sem) ->
+ mcode print_string goto; ident l; mcode print_string sem
+ | Ast.Return(ret,sem) ->
+ print_string arity; mcode print_string ret; mcode print_string sem
+ | Ast.ReturnExpr(ret,exp,sem) ->
+ print_string arity; mcode print_string ret; print_string " ";
+ expression exp; mcode print_string sem
+ | Ast.MetaRuleElem(name,_,_) ->
+ print_string arity; mcode print_meta name
+ | Ast.MetaStmt(name,_,_,_) ->
+ print_string arity; mcode print_meta name
+ | Ast.MetaStmtList(name,_,_) ->
+ print_string arity; mcode print_meta name
+ | Ast.Exp(exp) -> print_string arity; expression exp
+ | Ast.TopExp(exp) -> print_string arity; expression exp
+ | Ast.Ty(ty) -> print_string arity; fullType ty
+ | Ast.Include(inc,s) ->
+ mcode print_string inc; print_string " "; mcode inc_file s
+ | Ast.DefineHeader(def,id,params) ->
+ mcode print_string def; print_string " "; ident id;
+ print_define_parameters params
+ | Ast.Default(def,colon) ->
+ mcode print_string def; mcode print_string colon; print_string " "
+ | Ast.Case(case,exp,colon) ->
+ mcode print_string case; print_string " "; expression exp;
+ mcode print_string colon; print_string " "
+ | Ast.DisjRuleElem(res) ->
+ print_string arity;
+ force_newline(); print_string "("; force_newline();
+ print_between
+ (function _ -> force_newline();print_string "|"; force_newline())
+ (rule_elem arity)
+ res;
+ force_newline(); print_string ")"
+
+
+and print_define_parameters params =
+ match Ast.unwrap params with
+ Ast.NoParams -> ()
+ | Ast.DParams(lp,params,rp) ->
+ mcode print_string lp;
+ dots (function _ -> ()) print_define_param params; mcode print_string rp
+
+and print_define_param param =
+ match Ast.unwrap param with
+ Ast.DParam(id) -> ident id
+ | Ast.DPComma(comma) -> mcode print_string comma
+ | Ast.DPdots(dots) -> mcode print_string dots
+ | Ast.DPcircles(circles) -> mcode print_string circles
+ | Ast.OptDParam(dp) -> print_string "?"; print_define_param dp
+ | Ast.UniqueDParam(dp) -> print_string "!"; print_define_param dp
+
+and statement arity s =
+ match Ast.unwrap s with
+ Ast.Seq(lbrace,decls,body,rbrace) ->
+ rule_elem arity lbrace;
+ dots force_newline (statement arity) decls;
+ dots force_newline (statement arity) body;
+ rule_elem arity rbrace
+ | Ast.IfThen(header,branch,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity branch;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.IfThenElse(header,branch1,els,branch2,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity branch1; print_string " ";
+ rule_elem arity els; statement arity branch2;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.While(header,body,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity body;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.Do(header,body,tail) ->
+ rule_elem arity header; statement arity body;
+ rule_elem arity tail
+ | Ast.For(header,body,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity body;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.Iterator(header,body,(_,_,_,aft)) ->
+ rule_elem arity header; statement arity body;
+ mcode (function _ -> ()) ((),Ast.no_info,aft,Ast.NoMetaPos)
+ | Ast.Switch(header,lb,cases,rb) ->
+ rule_elem arity header; rule_elem arity lb;
+ List.iter (function x -> case_line arity x; force_newline()) cases;
+ rule_elem arity rb
+ | Ast.Atomic(re) -> rule_elem arity re
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ rule_elem arity header; rule_elem arity lbrace;
+ dots force_newline (statement arity) decls;
+ dots force_newline (statement arity) body;
+ rule_elem arity rbrace
+ | Ast.Disj([stmt_dots]) ->
+ print_string arity;
+ dots (function _ -> if !print_newlines_disj then force_newline())
+ (statement arity) stmt_dots
+ | Ast.Disj(stmt_dots_list) -> (* ignores newline directive for readability *)
+ print_string arity;
+ force_newline(); print_string "("; force_newline();
+ print_between
+ (function _ -> force_newline();print_string "|"; force_newline())
+ (dots force_newline (statement arity))
+ stmt_dots_list;
+ force_newline(); print_string ")"
+ | Ast.Define(header,body) ->
+ rule_elem arity header; print_string " ";
+ dots force_newline (statement arity) body
+ | Ast.Nest(stmt_dots,whn,multi,_,_) ->
+ print_string arity;
+ nest_dots multi (statement arity)
+ (function _ ->
+ open_box 0;
+ print_between force_newline
+ (whencode (dots force_newline (statement "")) (statement "")) whn;
+ close_box(); force_newline())
+ stmt_dots
+ | Ast.Dots(d,whn,_,_) | Ast.Circles(d,whn,_,_) | Ast.Stars(d,whn,_,_) ->
+ print_string arity; mcode print_string d;
+ open_box 0;
+ print_between force_newline
+ (whencode (dots force_newline (statement "")) (statement "")) whn;
+ close_box(); force_newline()
+ | Ast.OptStm(s) -> statement "?" s
+ | Ast.UniqueStm(s) -> statement "!" s
+
+and print_statement_when whencode =
+ print_string " WHEN != ";
+ open_box 0;
+ print_between (function _ -> print_string " &"; force_newline())
+ (dots force_newline (statement "")) whencode;
+ close_box()
+
+
+and whencode notfn alwaysfn = function
+ Ast.WhenNot a ->
+ print_string " WHEN != "; open_box 0; notfn a; close_box()
+ | Ast.WhenAlways a ->
+ print_string " WHEN = "; open_box 0; alwaysfn a; close_box()
+ | Ast.WhenModifier x -> print_string " WHEN "; print_when_modif x
+ | Ast.WhenNotTrue a ->
+ print_string " WHEN != TRUE "; open_box 0; rule_elem "" a; close_box()
+ | Ast.WhenNotFalse a ->
+ print_string " WHEN != FALSE "; open_box 0; rule_elem "" a; close_box()
+
+and print_when_modif = function
+ | Ast.WhenAny -> print_string "ANY"
+ | Ast.WhenStrict -> print_string "STRICT"
+ | Ast.WhenForall -> print_string "FORALL"
+ | Ast.WhenExists -> print_string "EXISTS"
+
+and case_line arity c =
+ match Ast.unwrap c with
+ Ast.CaseLine(header,code) ->
+ rule_elem arity header; print_string " ";
+ dots force_newline (statement arity) code
+ | Ast.OptCase(case) -> case_line "?" case
+
+(* --------------------------------------------------------------------- *)
+(* CPP code *)
+
+and inc_file = function
+ Ast.Local(elems) ->
+ print_string "\"";
+ print_between (function _ -> print_string "/") inc_elem elems;
+ print_string "\""
+ | Ast.NonLocal(elems) ->
+ print_string "<";
+ print_between (function _ -> print_string "/") inc_elem elems;
+ print_string ">"
+
+and inc_elem = function
+ Ast.IncPath s -> print_string s
+ | Ast.IncDots -> print_string "..."
+
+(* for export only *)
+let statement_dots l = dots force_newline (statement "") l
+
+let top_level t =
+ match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) ->
+ print_string "--- "; mcode print_string old_file; force_newline();
+ print_string "+++ "; mcode print_string new_file
+ | Ast.DECL(stmt) -> statement "" stmt
+ | Ast.CODE(stmt_dots) ->
+ dots force_newline (statement "") stmt_dots
+ | Ast.ERRORWORDS(exps) ->
+ print_string "error words = [";
+ print_between (function _ -> print_string ", ") expression exps;
+ print_string "]"
+
+let rule =
+ print_between (function _ -> force_newline(); force_newline()) top_level
+
+let pp_print_anything x = !anything x
+
+let _ =
+ anything := function
+ Ast.FullTypeTag(x) -> fullType x
+ | Ast.BaseTypeTag(x) -> baseType x
+ | Ast.StructUnionTag(x) -> structUnion x
+ | Ast.SignTag(x) -> sign x
+ | Ast.IdentTag(x) -> ident x
+ | Ast.ExpressionTag(x) -> expression x
+ | Ast.ConstantTag(x) -> constant x
+ | Ast.UnaryOpTag(x) -> unaryOp x
+ | Ast.AssignOpTag(x) -> assignOp x
+ | Ast.FixOpTag(x) -> fixOp x
+ | Ast.BinaryOpTag(x) -> binaryOp x
+ | Ast.ArithOpTag(x) -> arithOp x
+ | Ast.LogicalOpTag(x) -> logicalOp x
+ | Ast.InitTag(x) -> initialiser x
+ | Ast.DeclarationTag(x) -> declaration x
+ | Ast.StorageTag(x) -> storage x
+ | Ast.IncFileTag(x) -> inc_file x
+ | Ast.Rule_elemTag(x) -> rule_elem "" x
+ | Ast.StatementTag(x) -> statement "" x
+ | Ast.CaseLineTag(x) -> case_line "" x
+ | Ast.ConstVolTag(x) -> const_vol x
+ | Ast.Token(x,Some info) -> print_string_befaft print_string x info
+ | Ast.Token(x,None) -> print_string x
+ | Ast.Code(x) -> let _ = top_level x in ()
+ | Ast.ExprDotsTag(x) -> dots (function _ -> ()) expression x
+ | Ast.ParamDotsTag(x) -> parameter_list x
+ | Ast.StmtDotsTag(x) -> dots (function _ -> ()) (statement "") x
+ | Ast.DeclDotsTag(x) -> dots (function _ -> ()) declaration x
+ | Ast.TypeCTag(x) -> typeC x
+ | Ast.ParamTag(x) -> parameterTypeDef x
+ | Ast.SgrepStartTag(x) -> print_string x
+ | Ast.SgrepEndTag(x) -> print_string x
+
+let rec dep in_and = function
+ Ast.Dep(s) -> print_string s
+ | Ast.AntiDep(s) -> print_string "!"; print_string s
+ | Ast.EverDep(s) -> print_string "ever "; print_string s
+ | Ast.NeverDep(s) -> print_string "never "; print_string s
+ | Ast.AndDep(s1,s2) ->
+ let print_and _ = dep true s1; print_string " && "; dep true s2 in
+ if in_and
+ then print_and ()
+ else (print_string "("; print_and(); print_string ")")
+ | Ast.OrDep(s1,s2) ->
+ let print_or _ = dep false s1; print_string " || "; dep false s2 in
+ if not in_and
+ then print_or ()
+ else (print_string "("; print_or(); print_string ")")
+ | Ast.NoDep -> failwith "not possible"
+
+let unparse z =
+ match z with
+ Ast.ScriptRule (lang,deps,bindings,code) ->
+ print_string "@@";
+ force_newline();
+ print_string ("script:" ^ lang);
+ (match deps with
+ Ast.NoDep -> ()
+ | _ -> print_string " depends on "; dep true deps);
+ force_newline();
+ print_string "@@";
+ force_newline();
+ print_string code;
+ force_newline()
+ | Ast.CocciRule (nm, (deps, drops, exists), x, _) ->
+ print_string "@@";
+ force_newline();
+ print_string nm;
+ (match deps with
+ Ast.NoDep -> ()
+ | _ -> print_string " depends on "; dep true deps);
+ (*
+ print_string "line ";
+ print_int (Ast.get_line (List.hd x));
+ *)
+ force_newline();
+ print_string "@@";
+ print_newlines_disj := true;
+ force_newline();
+ force_newline();
+ rule x;
+ force_newline()
+
+let rule_elem_to_string x =
+ print_newlines_disj := true;
+ Common.format_to_string (function _ -> rule_elem "" x)
+
+let ident_to_string x =
+ print_newlines_disj := true;
+ Common.format_to_string (function _ -> ident x)
+
+let unparse_to_string x =
+ print_newlines_disj := true;
+ Common.format_to_string (function _ -> unparse x)
+
+let print_rule_elem re =
+ let nl = !print_newlines_disj in
+ print_newlines_disj := false;
+ rule_elem "" re;
+ print_newlines_disj := nl
+
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* detect statements that are between dots in the minus code, because they
+may need a special treatment if they are if branches *)
+
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module V0 = Visitor_ast0
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Helpers *)
+
+let left_dots f l =
+ match Ast0.undots l with
+ [] -> false
+ | x::xs -> f x
+
+let right_dots f l =
+ match List.rev (Ast0.undots l) with
+ [] -> false
+ | x::xs -> f x
+
+let modif_before_mcode mc =
+ match Ast0.get_mcode_mcodekind mc with
+ Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
+ | Ast0.PLUS -> failwith "not possible"
+ | Ast0.CONTEXT mc ->
+ (match !mc with
+ (Ast.BEFORE _,_,_) -> true
+ | (Ast.BEFOREAFTER _,_,_) -> true
+ | _ -> false)
+ | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
+
+let modif_after_mcodekind = function
+ Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
+ | Ast0.PLUS -> failwith "not possible"
+ | Ast0.CONTEXT mc ->
+ (match !mc with
+ (Ast.AFTER _,_,_) -> true
+ | (Ast.BEFOREAFTER _,_,_) -> true
+ | _ -> false)
+ | Ast0.MIXED mc -> true (* don't think mcode can be mixed *)
+
+let modif_after_mcode mc = modif_after_mcodekind (Ast0.get_mcode_mcodekind mc)
+
+let any_statements =
+ List.exists
+ (List.exists
+ (function
+ Ast.StatementTag(_) | Ast.StmtDotsTag(_)
+ | Ast.DeclarationTag(_) | Ast.DeclDotsTag(_) -> true | _ -> false))
+
+let modif_before x =
+ match Ast0.get_mcodekind x with
+ Ast0.PLUS -> failwith "not possible"
+ | Ast0.MINUS mc ->
+ (match !mc with
+ (* do better for the common case of replacing a stmt by another one *)
+ ([[Ast.StatementTag(s)]],_) ->
+ (match Ast.unwrap s with
+ Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
+ | _ -> false)
+ | (_,_) -> true)
+ | Ast0.CONTEXT mc | Ast0.MIXED mc ->
+ (match !mc with
+ (Ast.BEFORE _,_,_) -> true
+ | (Ast.BEFOREAFTER _,_,_) -> true
+ | _ -> false)
+
+let modif_after x =
+ match Ast0.get_mcodekind x with
+ Ast0.PLUS -> failwith "not possible"
+ | Ast0.MINUS mc ->
+ (match !mc with
+ (* do better for the common case of replacing a stmt by another one *)
+ ([[Ast.StatementTag(s)]],_) ->
+ (match Ast.unwrap s with
+ Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
+ | _ -> false)
+ | (l,_) -> any_statements l)
+ | Ast0.CONTEXT mc | Ast0.MIXED mc ->
+ (match !mc with
+ (Ast.AFTER _,_,_) -> true
+ | (Ast.BEFOREAFTER _,_,_) -> true
+ | _ -> false)
+
+(* Identifier *)
+let rec left_ident i =
+ modif_before i or
+ match Ast0.unwrap i with
+ Ast0.Id(name) -> modif_before_mcode name
+ | Ast0.MetaId(name,_,_) -> modif_before_mcode name
+ | Ast0.MetaFunc(name,_,_) -> modif_before_mcode name
+ | Ast0.MetaLocalFunc(name,_,_) -> modif_before_mcode name
+ | Ast0.OptIdent(id) -> left_ident id
+ | Ast0.UniqueIdent(id) -> left_ident id
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let rec left_expression e =
+ modif_before e or
+ match Ast0.unwrap e with
+ Ast0.Ident(id) -> left_ident id
+ | Ast0.Constant(const) -> modif_before_mcode const
+ | Ast0.FunCall(fn,lp,args,rp) -> left_expression fn
+ | Ast0.Assignment(left,op,right,_) -> left_expression left
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) -> left_expression exp1
+ | Ast0.Postfix(exp,op) -> left_expression exp
+ | Ast0.Infix(exp,op) -> modif_before_mcode op
+ | Ast0.Unary(exp,op) -> modif_before_mcode op
+ | Ast0.Binary(left,op,right) -> left_expression left
+ | Ast0.Nested(left,op,right) -> left_expression left
+ | Ast0.Paren(lp,exp,rp) -> modif_before_mcode lp
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) -> left_expression exp1
+ | Ast0.RecordAccess(exp,pt,field) -> left_expression exp
+ | Ast0.RecordPtAccess(exp,ar,field) -> left_expression exp
+ | Ast0.Cast(lp,ty,rp,exp) -> modif_before_mcode lp
+ | Ast0.SizeOfExpr(szf,exp) -> modif_before_mcode szf
+ | Ast0.SizeOfType(szf,lp,ty,rp) -> modif_before_mcode szf
+ | Ast0.TypeExp(ty) -> left_typeC ty
+ | Ast0.MetaErr(name,_,_) -> modif_before_mcode name
+ | Ast0.MetaExpr(name,_,ty,_,_) -> modif_before_mcode name
+ | Ast0.MetaExprList(name,_,_) -> modif_before_mcode name
+ | Ast0.EComma(cm) -> modif_before_mcode cm
+ | Ast0.DisjExpr(_,exp_list,_,_) -> List.exists left_expression exp_list
+ | Ast0.NestExpr(starter,expr_dots,ender,_,multi) ->
+ left_dots left_expression expr_dots
+ | Ast0.Edots(dots,_) | Ast0.Ecircles(dots,_) | Ast0.Estars(dots,_) -> false
+ | Ast0.OptExp(exp) -> left_expression exp
+ | Ast0.UniqueExp(exp) -> left_expression exp
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and left_typeC t =
+ modif_before t or
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> modif_before_mcode cv
+ | Ast0.BaseType(ty,Some sgn) -> modif_before_mcode sgn
+ | Ast0.BaseType(ty,None) -> modif_before_mcode ty
+ | Ast0.ImplicitInt(sgn) -> modif_before_mcode sgn
+ | Ast0.Pointer(ty,star) -> left_typeC ty
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) -> left_typeC ty
+ | Ast0.FunctionType(Some ty,lp1,params,rp1) -> left_typeC ty
+ | Ast0.FunctionType(None,lp1,params,rp1) -> modif_before_mcode lp1
+ | Ast0.Array(ty,lb,size,rb) -> left_typeC ty
+ | Ast0.StructUnionName(kind,name) -> modif_before_mcode kind
+ | Ast0.StructUnionDef(ty,lb,decls,rb) -> left_typeC ty
+ | Ast0.TypeName(name) -> modif_before_mcode name
+ | Ast0.MetaType(name,_) -> modif_before_mcode name
+ | Ast0.DisjType(lp,types,mids,rp) -> List.exists left_typeC types
+ | Ast0.OptType(ty) -> left_typeC ty
+ | Ast0.UniqueType(ty) -> left_typeC ty
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and left_declaration d =
+ modif_before d or
+ match Ast0.unwrap d with
+ Ast0.Init(Some stg,ty,id,eq,ini,sem) -> modif_before_mcode stg
+ | Ast0.Init(None,ty,id,eq,ini,sem) -> left_typeC ty
+ | Ast0.UnInit(Some stg,ty,id,sem) -> modif_before_mcode stg
+ | Ast0.UnInit(None,ty,id,sem) -> left_typeC ty
+ | Ast0.MacroDecl(name,lp,args,rp,sem) -> left_ident name
+ | Ast0.TyDecl(ty,sem) -> left_typeC ty
+ | Ast0.Typedef(stg,ty,id,sem) -> modif_before_mcode stg
+ | Ast0.DisjDecl(_,decls,_,_) -> List.exists left_declaration decls
+ | Ast0.Ddots(dots,_) -> false
+ | Ast0.OptDecl(decl) -> left_declaration decl
+ | Ast0.UniqueDecl(decl) -> left_declaration decl
+
+and right_declaration d =
+ modif_before d or
+ match Ast0.unwrap d with
+ Ast0.Init(_,ty,id,eq,ini,sem) -> modif_after_mcode sem
+ | Ast0.UnInit(_,ty,id,sem) -> modif_after_mcode sem
+ | Ast0.MacroDecl(name,lp,args,rp,sem) -> modif_after_mcode sem
+ | Ast0.TyDecl(ty,sem) -> modif_after_mcode sem
+ | Ast0.Typedef(stg,ty,id,sem) -> modif_after_mcode sem
+ | Ast0.DisjDecl(_,decls,_,_) -> List.exists right_declaration decls
+ | Ast0.Ddots(dots,_) -> false
+ | Ast0.OptDecl(decl) -> right_declaration decl
+ | Ast0.UniqueDecl(decl) -> right_declaration decl
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and left_statement s =
+ modif_before s or
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ (* irrelevant *) false
+ | Ast0.Decl(_,decl) -> left_declaration decl
+ | Ast0.Seq(lbrace,body,rbrace) -> modif_before_mcode lbrace
+ | Ast0.ExprStatement(exp,sem) -> left_expression exp
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_before_mcode iff
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
+ modif_before_mcode iff
+ | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_before_mcode whl
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_before_mcode d
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
+ modif_before_mcode fr
+ | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) -> left_ident nm
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) -> modif_before_mcode switch
+ | Ast0.Break(br,sem) -> modif_before_mcode br
+ | Ast0.Continue(cont,sem) -> modif_before_mcode cont
+ | Ast0.Label(l,dd) -> left_ident l
+ | Ast0.Goto(goto,l,sem) -> modif_before_mcode goto
+ | Ast0.Return(ret,sem) -> modif_before_mcode ret
+ | Ast0.ReturnExpr(ret,exp,sem) -> modif_before_mcode ret
+ | Ast0.MetaStmt(name,pure) -> modif_before_mcode name
+ | Ast0.MetaStmtList(name,_) -> modif_before_mcode name
+ | Ast0.Disj(_,statement_dots_list,_,_) ->
+ List.exists (left_dots left_statement) statement_dots_list
+ | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
+ left_dots left_statement stmt_dots
+ | Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
+ | Ast0.TopExp(exp) -> false (* as above *)
+ | Ast0.Ty(ty) -> false (* can only be replaced by a type *)
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
+ | Ast0.Include(inc,s) -> modif_before_mcode inc
+ | Ast0.Define(def,id,params,body) -> modif_before_mcode def
+ | Ast0.OptStm(re) -> left_statement re
+ | Ast0.UniqueStm(re) -> left_statement re
+
+and right_statement s =
+ modif_after s or
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ (* irrelevant *) false
+ | Ast0.Decl(_,decl) -> right_declaration decl
+ | Ast0.Seq(lbrace,body,rbrace) -> modif_after_mcode rbrace
+ | Ast0.ExprStatement(exp,sem) -> modif_after_mcode sem
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) -> modif_after_mcodekind aft
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
+ modif_after_mcodekind aft
+ | Ast0.While(whl,lp,exp,rp,body,(info,aft)) -> modif_after_mcodekind aft
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) -> modif_after_mcode sem
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
+ modif_after_mcodekind aft
+ | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) ->
+ modif_after_mcodekind aft
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) -> modif_after_mcode rb
+ | Ast0.Break(br,sem) -> modif_after_mcode sem
+ | Ast0.Continue(cont,sem) -> modif_after_mcode sem
+ | Ast0.Label(l,dd) -> modif_after_mcode dd
+ | Ast0.Goto(goto,l,sem) -> modif_after_mcode sem
+ | Ast0.Return(ret,sem) -> modif_after_mcode sem
+ | Ast0.ReturnExpr(ret,exp,sem) -> modif_after_mcode sem
+ | Ast0.MetaStmt(name,pure) -> modif_after_mcode name
+ | Ast0.MetaStmtList(name,_) -> modif_after_mcode name
+ | Ast0.Disj(_,statement_dots_list,_,_) ->
+ List.exists (right_dots right_statement) statement_dots_list
+ | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
+ right_dots right_statement stmt_dots
+ | Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
+ | Ast0.TopExp(exp) -> false (* as above *)
+ | Ast0.Ty(ty) -> false (* can only be replaced by a type *)
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
+ | Ast0.Include(inc,s) -> modif_after_mcode s
+ | Ast0.Define(def,id,params,body) -> right_dots right_statement body
+ | Ast0.OptStm(re) -> right_statement re
+ | Ast0.UniqueStm(re) -> right_statement re
+
+(* --------------------------------------------------------------------- *)
+
+
+(* A very coarse approximation. We would really only like to return true
+if a new statement is added. For this it would be best to correlate with the
+plus slice. Or at least be sure that the new stuff is on the far left or
+far right. *)
+
+let rec adding_something s =
+ match Ast0.get_mcodekind s with
+ Ast0.MINUS(mc) ->
+ (match !mc with
+ (* do better for the common case of replacing a stmt by another one *)
+ ([[Ast.StatementTag(s)]],_) ->
+ (match Ast.unwrap s with
+ Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
+ | _ -> false)
+ | (_,_) -> true)
+ | Ast0.CONTEXT(mc) ->
+ let (text,tinfo1,tinfo2) = !mc in
+ (match text with Ast.NOTHING -> false | _ -> true)
+ | Ast0.MIXED(_) ->
+ not(contains_only_minus.V0.combiner_statement s) (*&&
+ (left_statement s) or (right_statement s)*)
+ | _ -> failwith "unexpected plus code"
+
+(* why do we need this; MINUS should mean the same thing *)
+and contains_only_minus =
+ let bind x y = x && y in
+ let option_default = true in
+ let mcodekind = function
+ Ast0.MINUS(mc) ->
+ (match !mc with
+ ([],_) -> true
+ | _ -> false)
+ | Ast0.CONTEXT(mc) -> false
+ | _ -> false in
+ let mcode (_,_,_,mc,_) = mcodekind mc in
+
+ let donothing r k e = mcodekind (Ast0.get_mcodekind e) && k e in
+
+ let dots r k e =
+ match Ast0.unwrap e with
+ Ast0.DOTS([]) | Ast0.CIRCLES([]) | Ast0.STARS([]) -> true
+ | _ -> k e in
+
+ let expression r k e =
+ mcodekind (Ast0.get_mcodekind e) &&
+ match Ast0.unwrap e with
+ Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ List.for_all r.V0.combiner_expression expr_list
+ | _ -> k e in
+
+ let declaration r k e =
+ mcodekind (Ast0.get_mcodekind e) &&
+ match Ast0.unwrap e with
+ Ast0.DisjDecl(starter,decls,mids,ender) ->
+ List.for_all r.V0.combiner_declaration decls
+ | _ -> k e in
+
+ let typeC r k e =
+ mcodekind (Ast0.get_mcodekind e) &&
+ match Ast0.unwrap e with
+ Ast0.DisjType(starter,types,mids,ender) ->
+ List.for_all r.V0.combiner_typeC types
+ | _ -> k e in
+
+ let statement r k e =
+ mcodekind (Ast0.get_mcodekind e) &&
+ match Ast0.unwrap e with
+ Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ List.for_all r.V0.combiner_statement_dots statement_dots_list
+ | _ -> k e in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ dots dots dots dots dots dots
+ donothing expression typeC donothing donothing declaration
+ statement donothing donothing
+
+
+(* needs a special case when there is a Disj or an empty DOTS *)
+(* ---------------------------------------------------------------------- *)
+
+(*
+Doesn't really work:
+
+ if (acpi_device_dir(device))
++ {
+ remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
++ acpi_device_dir(device) = NULL;
++ }
+
+The last two + lines get associated with the end of the if, not with the
+branch, so the braces get added in oddly.
+*)
+
+let add_braces orig_s =
+ let s = (Iso_pattern.rebuild_mcode None).V0.rebuilder_statement orig_s in
+ let new_mcodekind =
+ match Ast0.get_mcodekind s with
+ Ast0.MINUS(mc) ->
+ let (text,tinfo) = !mc in
+ Ast0.MINUS(ref([Ast.mkToken "{"]::text@[[Ast.mkToken "}"]],tinfo))
+ | Ast0.CONTEXT(mc) ->
+ let (text,tinfo1,tinfo2) = !mc in
+ let new_text =
+ match text with
+ Ast.BEFORE(bef) ->
+ Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]])
+ | Ast.AFTER(aft) ->
+ Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]])
+ | Ast.BEFOREAFTER(bef,aft) ->
+ Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]])
+ | Ast.NOTHING ->
+ Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) in
+ Ast0.CONTEXT(ref(new_text,tinfo1,tinfo2))
+ | Ast0.MIXED(mc) ->
+ let (text,tinfo1,tinfo2) = !mc in
+ let new_text =
+ match text with
+ Ast.BEFORE(bef) ->
+ Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]])
+ | Ast.AFTER(aft) ->
+ Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]])
+ | Ast.BEFOREAFTER(bef,aft) ->
+ Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]])
+ | Ast.NOTHING ->
+ Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) in
+ Ast0.MIXED(ref(new_text,tinfo1,tinfo2))
+ | _ -> failwith "unexpected plus code" in
+ Ast0.set_mcodekind s new_mcodekind;
+ Compute_lines.statement s
+
+(* ---------------------------------------------------------------------- *)
+
+let is_dots x =
+ match Ast0.unwrap x with
+ Ast0.Dots(_,_) | Ast0.Circles(_,_) | Ast0.Stars(_,_)
+ | Ast0.Nest(_,_,_,_,_) -> true
+ | _ -> false
+
+let all_minus s =
+ match Ast0.get_mcodekind s with
+ Ast0.MINUS(_) -> true
+ | _ -> false
+
+let rec unchanged_minus s =
+ match Ast0.get_mcodekind s with
+ Ast0.MINUS(mc) -> (match !mc with ([],_) -> true | _ -> false)
+ | _ -> false
+
+let rec do_branch s =
+ if unchanged_minus s
+ then
+ Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(add_braces s))
+ else
+ match Ast0.unwrap s with
+ Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ let stmts =
+ List.map
+ (function s ->
+ match Ast0.unwrap s with
+ Ast0.DOTS([s]) ->
+ Ast0.rewrap s (Ast0.DOTS([do_branch s]))
+ | Ast0.DOTS(_) -> s
+ | _ -> failwith "not supported")
+ statement_dots_list in
+ Ast0.rewrap s (Ast0.Disj(starter,stmts,mids,ender))
+ | _ -> s
+
+let rec statement dots_before dots_after s =
+ let do_one s =
+ if dots_before && dots_after
+ then
+ if unchanged_minus s
+ then
+ (let with_braces = add_braces s in
+ Ast0.set_dots_bef_aft s (Ast0.DroppingBetweenDots(with_braces)))
+ else if adding_something s
+ then
+ (let with_braces = add_braces s in
+ Ast0.set_dots_bef_aft s (Ast0.AddingBetweenDots(with_braces)))
+ else s
+ else s in
+
+ match Ast0.unwrap s with
+ Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ (* true for close brace, because that represents any way we can
+ exit the function, which is not necessarily followed by an explicit
+ close brace. *)
+ Ast0.rewrap s
+ (Ast0.FunDecl(x,fninfo,name,lp,params,rp,lbrace,
+ statement_dots false true body,
+ rbrace))
+ | Ast0.Decl(_,_) -> s
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ Ast0.rewrap s
+ (Ast0.Seq(lbrace,statement_dots false false body,rbrace))
+ | Ast0.ExprStatement(exp,sem) -> do_one s
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,x) ->
+ do_one
+ (Ast0.rewrap s
+ (Ast0.IfThen(iff,lp,exp,rp,statement false false branch1,x)))
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,x) ->
+ do_one
+ (Ast0.rewrap s
+ (Ast0.IfThenElse
+ (iff,lp,exp,rp,
+ statement false false branch1,els,
+ statement false false branch2,x)))
+ | Ast0.While(whl,lp,exp,rp,body,x) ->
+ do_one
+ (Ast0.rewrap s
+ (Ast0.While(whl,lp,exp,rp,statement false false body,x)))
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
+ do_one
+ (Ast0.rewrap s
+ (Ast0.Do(d,statement false false body,whl,lp,exp,rp,sem)))
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,x) ->
+ do_one
+ (Ast0.rewrap s
+ (Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,
+ statement false false body,x)))
+ | Ast0.Iterator(nm,lp,args,rp,body,x) ->
+ do_one
+ (Ast0.rewrap s
+ (Ast0.Iterator(nm,lp,args,rp,statement false false body,x)))
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ do_one
+ (Ast0.rewrap s
+ (Ast0.Switch(switch,lp,exp,rp,lb,
+ Ast0.rewrap cases
+ (Ast0.DOTS(List.map case_line (Ast0.undots cases))),
+ rb)))
+ | Ast0.Break(br,sem) -> do_one s
+ | Ast0.Continue(cont,sem) -> do_one s
+ | Ast0.Label(l,dd) -> do_one s
+ | Ast0.Goto(goto,l,sem) -> do_one s
+ | Ast0.Return(ret,sem) -> do_one s
+ | Ast0.ReturnExpr(ret,exp,sem) -> do_one s
+ | Ast0.MetaStmt(name,_) -> do_one s
+ | Ast0.MetaStmtList(name,_) -> do_one s
+ | Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ Ast0.rewrap s
+ (Ast0.Disj(starter,
+ List.map (statement_dots dots_before dots_after)
+ statement_dots_list,
+ mids,ender))
+ | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
+ Ast0.rewrap s
+ (Ast0.Nest
+ (starter,statement_dots true true stmt_dots,ender,whencode,multi))
+ | Ast0.Exp(exp) -> s
+ | Ast0.TopExp(exp) -> s
+ | Ast0.Ty(ty) -> s
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> s
+ | Ast0.Include(inc,string) -> s (* doesn't affect the need for braces *)
+ | Ast0.Define(def,id,params,body) -> s (* same as include *)
+ | Ast0.OptStm(re) ->
+ Ast0.rewrap s
+ (Ast0.OptStm(statement dots_before dots_after re))
+ | Ast0.UniqueStm(re) ->
+ Ast0.rewrap s
+ (Ast0.UniqueStm(statement dots_before dots_after re))
+
+and case_line c =
+ Ast0.rewrap c
+ (match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ Ast0.Default(def,colon,statement_dots false false code)
+ | Ast0.Case(case,exp,colon,code) ->
+ Ast0.Case(case,exp,colon,statement_dots false false code)
+ | Ast0.OptCase(case) -> Ast0.OptCase(case_line c))
+
+and do_statement_dots dots_before dots_after = function
+ [] -> []
+ | [x] -> [statement dots_before dots_after x]
+ | dots::rest when is_dots dots ->
+ dots::(do_statement_dots true dots_after rest)
+ | x::(dots::_ as rest) when is_dots dots ->
+ (statement dots_before true x)::
+ do_statement_dots false dots_after rest
+ | x::rest ->
+ (statement dots_before false x)::
+ do_statement_dots false dots_after rest
+
+and statement_dots dots_before dots_after d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) ->
+ Ast0.DOTS(do_statement_dots dots_before dots_after l)
+ | Ast0.CIRCLES(l) ->
+ Ast0.CIRCLES(do_statement_dots dots_before dots_after l)
+ | Ast0.STARS(l) ->
+ Ast0.STARS(do_statement_dots dots_before dots_after l))
+
+let top_level t =
+ Ast0.rewrap t
+ (match Ast0.unwrap t with
+ Ast0.DECL(stmt_dots) -> Ast0.DECL(statement true true stmt_dots)
+ | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots true true stmt_dots)
+ | t -> t)
+
+let single_statement l =
+ if !Flag_parsing_cocci.sgrep_mode then l else List.map top_level l
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+
+(* call set_test_pos on test expressions *)
+
+(* The goal of this is to identify test expressions in the SmPL file, so that
+isomorphisms like X != NULL => X are only applied in a test expression context.
+
+There is a related check in cocci_vs_c3.ml that in x || ..., a match
+without the || is only accepted in a test expression context. This uses
+the annotations in the C file. *)
+
+let rec process_exp e =
+ let e = Ast0.set_test_pos e in
+ match Ast0.unwrap e with
+ Ast0.Paren(lp,e,rp) ->
+ Ast0.rewrap e (Ast0.Paren(lp,process_exp e,rp))
+ | _ -> e
+
+let set_test_poss =
+ let donothing r k e = k e in
+ let mcode x = x in
+
+ let expression r k e =
+ let e = k e in
+ match Ast0.unwrap e with
+ Ast0.CondExpr(e1,q,e2,c,e3) ->
+ Ast0.rewrap e (Ast0.CondExpr(process_exp e1,q,e2,c,e3))
+ | Ast0.Binary(e1,op,e2) ->
+ (match Ast0.unwrap_mcode op with
+ Ast.Logical(Ast.AndLog) | Ast.Logical(Ast.OrLog) ->
+ Ast0.rewrap e (Ast0.Binary(process_exp e1,op,process_exp e2))
+ | _ -> e)
+ | Ast0.Unary(e1,op) ->
+ (match Ast0.unwrap_mcode op with
+ Ast.Not -> Ast0.rewrap e (Ast0.Unary(process_exp e1,op))
+ | _ -> e)
+ | _ -> e in
+
+ let statement r k s =
+ let s = k s in
+ match Ast0.unwrap s with
+ Ast0.IfThen(i,lp,e,rp,s1,aft) ->
+ Ast0.rewrap s (Ast0.IfThen(i,lp,process_exp e,rp,s1,aft))
+ | Ast0.IfThenElse(i,lp,e,rp,s1,e1,s2,aft) ->
+ Ast0.rewrap s (Ast0.IfThenElse(i,lp,process_exp e,rp,s1,e1,s2,aft))
+ | Ast0.While(i,lp,e,rp,s1,aft) ->
+ Ast0.rewrap s (Ast0.While(i,lp,process_exp e,rp,s1,aft))
+ | Ast0.Do(d,s1,w,lp,e,rp,sc) ->
+ Ast0.rewrap s (Ast0.Do(d,s1,w,lp,process_exp e,rp,sc))
+ | Ast0.For(f,lp,e1,sc1,Some e2,sc2,e3,rp,s1,aft) ->
+ Ast0.rewrap s
+ (Ast0.For(f,lp,e1,sc1,Some (process_exp e2),sc2,e3,rp,s1,aft))
+ | _ -> s in
+
+ V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ donothing expression donothing donothing donothing donothing statement
+ donothing donothing
+
+let process = List.map set_test_poss.V0.rebuilder_top_level
+
+let process_anything = set_test_poss.V0.rebuilder_anything
+
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module T = Type_cocci
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+module V0 = Visitor_ast0
+
+(* Type inference:
+Just propagates information based on declarations. Could try to infer
+more precise information about expression metavariables, but not sure it is
+worth it. The most obvious goal is to distinguish between test expressions
+that have pointer, integer, and boolean type when matching isomorphisms,
+but perhaps other needs will become apparent. *)
+
+(* "functions" that return a boolean value *)
+let bool_functions = ["likely";"unlikely"]
+
+let err wrapped ty s =
+ T.typeC ty; Format.print_newline();
+ failwith (Printf.sprintf "line %d: %s" (Ast0.get_line wrapped) s)
+
+type id = Id of string | Meta of (string * string)
+
+let rec lub_type t1 t2 =
+ match (t1,t2) with
+ (None,None) -> None
+ | (None,Some t) -> t2
+ | (Some t,None) -> t1
+ | (Some t1,Some t2) ->
+ let rec loop = function
+ (T.Unknown,t2) -> t2
+ | (t1,T.Unknown) -> t1
+ | (T.ConstVol(cv1,ty1),T.ConstVol(cv2,ty2)) when cv1 = cv2 ->
+ T.ConstVol(cv1,loop(ty1,ty2))
+ | (T.Pointer(ty1),T.Pointer(ty2)) ->
+ T.Pointer(loop(ty1,ty2))
+ | (ty1,T.Pointer(ty2)) -> T.Pointer(ty2)
+ | (T.Pointer(ty1),ty2) -> T.Pointer(ty1)
+ | (T.Array(ty1),T.Array(ty2)) -> T.Array(loop(ty1,ty2))
+ | (T.TypeName(s1),t2) -> t2
+ | (t1,T.TypeName(s1)) -> t1
+ | (t1,_) -> t1 in (* arbitrarily pick the first, assume type correct *)
+ Some (loop (t1,t2))
+
+let lub_envs envs =
+ List.fold_left
+ (function acc ->
+ function env ->
+ List.fold_left
+ (function acc ->
+ function (var,ty) ->
+ let (relevant,irrelevant) =
+ List.partition (function (x,_) -> x = var) acc in
+ match relevant with
+ [] -> (var,ty)::acc
+ | [(x,ty1)] ->
+ (match lub_type (Some ty) (Some ty1) with
+ Some new_ty -> (var,new_ty)::irrelevant
+ | None -> irrelevant)
+ | _ -> failwith "bad type environment")
+ acc env)
+ [] envs
+
+let rec propagate_types env =
+ let option_default = None in
+ let bind x y = option_default in (* no generic way of combining types *)
+
+ let mcode x = option_default in
+
+ let ident r k i =
+ match Ast0.unwrap i with
+ Ast0.Id(id) ->
+ (try Some(List.assoc (Id(Ast0.unwrap_mcode id)) env)
+ with Not_found -> None)
+ | Ast0.MetaId(id,_,_) ->
+ (try Some(List.assoc (Meta(Ast0.unwrap_mcode id)) env)
+ with Not_found -> None)
+ | _ -> k i in
+
+ let strip_cv = function
+ Some (T.ConstVol(_,t)) -> Some t
+ | t -> t in
+
+ let expression r k e =
+ let res = k e in
+ let ty =
+ match Ast0.unwrap e with
+ Ast0.Ident(id) -> Ast0.set_type e res; res
+ | Ast0.Constant(const) ->
+ (match Ast0.unwrap_mcode const with
+ Ast.String(_) -> Some (T.Pointer(T.BaseType(T.CharType,None)))
+ | Ast.Char(_) -> Some (T.BaseType(T.CharType,None))
+ | Ast.Int(_) -> Some (T.BaseType(T.IntType,None))
+ | Ast.Float(_) -> Some (T.BaseType(T.FloatType,None)))
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ (match Ast0.get_type fn with
+ Some (T.FunctionPointer(ty)) -> Some ty
+ | _ ->
+ (match Ast0.unwrap fn with
+ Ast0.Ident(id) ->
+ (match Ast0.unwrap id with
+ Ast0.Id(id) ->
+ if List.mem (Ast0.unwrap_mcode id) bool_functions
+ then Some(T.BaseType(T.BoolType,None))
+ else None
+ | _ -> None)
+ | _ -> None))
+ | Ast0.Assignment(exp1,op,exp2,_) ->
+ let ty = lub_type (Ast0.get_type exp1) (Ast0.get_type exp2) in
+ Ast0.set_type exp1 ty; Ast0.set_type exp2 ty; ty
+ | Ast0.CondExpr(exp1,why,Some exp2,colon,exp3) ->
+ let ty = lub_type (Ast0.get_type exp2) (Ast0.get_type exp3) in
+ Ast0.set_type exp2 ty; Ast0.set_type exp3 ty; ty
+ | Ast0.CondExpr(exp1,why,None,colon,exp3) -> Ast0.get_type exp3
+ | Ast0.Postfix(exp,op) | Ast0.Infix(exp,op) -> (* op is dec or inc *)
+ Ast0.get_type exp
+ | Ast0.Unary(exp,op) ->
+ (match Ast0.unwrap_mcode op with
+ Ast.GetRef ->
+ (match Ast0.get_type exp with
+ None -> Some (T.Pointer(T.Unknown))
+ | Some t -> Some (T.Pointer(t)))
+ | Ast.DeRef ->
+ (match Ast0.get_type exp with
+ Some (T.Pointer(t)) -> Some t
+ | _ -> None)
+ | Ast.UnPlus -> Ast0.get_type exp
+ | Ast.UnMinus -> Ast0.get_type exp
+ | Ast.Tilde -> Ast0.get_type exp
+ | Ast.Not -> Some(T.BaseType(T.BoolType,None)))
+ | Ast0.Nested(exp1,op,exp2) -> failwith "nested in type inf not possible"
+ | Ast0.Binary(exp1,op,exp2) ->
+ let ty1 = Ast0.get_type exp1 in
+ let ty2 = Ast0.get_type exp2 in
+ let same_type = function
+ (None,None) -> Some (T.BaseType(T.IntType,None))
+ | (Some (T.Pointer ty1),Some ty2) ->
+ Some (T.Pointer ty1)
+ | (Some ty1,Some (T.Pointer ty2)) ->
+ Some (T.Pointer ty2)
+ | (t1,t2) ->
+ let ty = lub_type t1 t2 in
+ Ast0.set_type exp1 ty; Ast0.set_type exp2 ty; ty in
+ (match Ast0.unwrap_mcode op with
+ Ast.Arith(op) -> same_type (ty1, ty2)
+ | Ast.Logical(op) ->
+ let ty = lub_type ty1 ty2 in
+ Ast0.set_type exp1 ty; Ast0.set_type exp2 ty;
+ Some(T.BaseType(T.BoolType,None)))
+ | Ast0.Paren(lp,exp,rp) -> Ast0.get_type exp
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ (match strip_cv (Ast0.get_type exp2) with
+ None -> Ast0.set_type exp2 (Some(T.BaseType(T.IntType,None)))
+ | Some(T.BaseType(T.IntType,None)) -> ()
+ | Some (T.MetaType(_,_,_)) -> ()
+ | Some (T.TypeName _) -> ()
+ | Some ty -> err exp2 ty "bad type for an array index");
+ (match strip_cv (Ast0.get_type exp1) with
+ None -> None
+ | Some (T.Array(ty)) -> Some ty
+ | Some (T.Pointer(ty)) -> Some ty
+ | Some (T.MetaType(_,_,_)) -> None
+ | Some x -> err exp1 x "ill-typed array reference")
+ | Ast0.RecordAccess(exp,pt,field) ->
+ (match strip_cv (Ast0.get_type exp) with
+ None -> None
+ | Some (T.StructUnionName(_,_,_)) -> None
+ | Some (T.TypeName(_)) -> None
+ | Some (T.MetaType(_,_,_)) -> None
+ | Some x -> err exp x "non-structure type in field ref")
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ (match strip_cv (Ast0.get_type exp) with
+ None -> None
+ | Some (T.Pointer(t)) ->
+ (match strip_cv (Some t) with
+ | Some (T.Unknown) -> None
+ | Some (T.MetaType(_,_,_)) -> None
+ | Some (T.TypeName(_)) -> None
+ | Some (T.StructUnionName(_,_,_)) -> None
+ | Some x ->
+ err exp (T.Pointer(t))
+ "non-structure pointer type in field ref"
+ | _ -> failwith "not possible")
+ | Some (T.MetaType(_,_,_)) -> None
+ | Some (T.TypeName(_)) -> None
+ | Some x -> err exp x "non-structure pointer type in field ref")
+ | Ast0.Cast(lp,ty,rp,exp) -> Some(Ast0.ast0_type_to_type ty)
+ | Ast0.SizeOfExpr(szf,exp) -> Some(T.BaseType(T.IntType,None))
+ | Ast0.SizeOfType(szf,lp,ty,rp) -> Some(T.BaseType(T.IntType,None))
+ | Ast0.TypeExp(ty) -> None
+ | Ast0.MetaErr(name,_,_) -> None
+ | Ast0.MetaExpr(name,_,Some [ty],_,_) -> Some ty
+ | Ast0.MetaExpr(name,_,ty,_,_) -> None
+ | Ast0.MetaExprList(name,_,_) -> None
+ | Ast0.EComma(cm) -> None
+ | Ast0.DisjExpr(_,exp_list,_,_) ->
+ let types = List.map Ast0.get_type exp_list in
+ let combined = List.fold_left lub_type None types in
+ (match combined with
+ None -> None
+ | Some t ->
+ List.iter (function e -> Ast0.set_type e (Some t)) exp_list;
+ Some t)
+ | Ast0.NestExpr(starter,expr_dots,ender,None,multi) ->
+ let _ = r.V0.combiner_expression_dots expr_dots in None
+ | Ast0.NestExpr(starter,expr_dots,ender,Some e,multi) ->
+ let _ = r.V0.combiner_expression_dots expr_dots in
+ let _ = r.V0.combiner_expression e in None
+ | Ast0.Edots(_,None) | Ast0.Ecircles(_,None) | Ast0.Estars(_,None) ->
+ None
+ | Ast0.Edots(_,Some e) | Ast0.Ecircles(_,Some e)
+ | Ast0.Estars(_,Some e) ->
+ let _ = r.V0.combiner_expression e in None
+ | Ast0.OptExp(exp) -> Ast0.get_type exp
+ | Ast0.UniqueExp(exp) -> Ast0.get_type exp in
+ Ast0.set_type e ty;
+ ty in
+
+ let donothing r k e = k e in
+
+ let rec strip id =
+ match Ast0.unwrap id with
+ Ast0.Id(name) -> Id(Ast0.unwrap_mcode name)
+ | Ast0.MetaId(name,_,_) -> Meta(Ast0.unwrap_mcode name)
+ | Ast0.MetaFunc(name,_,_) -> Meta(Ast0.unwrap_mcode name)
+ | Ast0.MetaLocalFunc(name,_,_) -> Meta(Ast0.unwrap_mcode name)
+ | Ast0.OptIdent(id) -> strip id
+ | Ast0.UniqueIdent(id) -> strip id in
+
+ let process_whencode notfn allfn = function
+ Ast0.WhenNot(x) -> let _ = notfn x in ()
+ | Ast0.WhenAlways(x) -> let _ = allfn x in ()
+ | Ast0.WhenModifier(_) -> () in
+
+ (* assume that all of the declarations are at the beginning of a statement
+ list, which is required by C, but not actually required by the cocci
+ parser *)
+ let rec process_statement_list r acc = function
+ [] -> acc
+ | (s::ss) ->
+ (match Ast0.unwrap s with
+ Ast0.Decl(_,decl) ->
+ let rec process_decl decl =
+ match Ast0.unwrap decl with
+ Ast0.Init(_,ty,id,_,exp,_) ->
+ let _ =
+ (propagate_types acc).V0.combiner_initialiser exp in
+ [(strip id,Ast0.ast0_type_to_type ty)]
+ | Ast0.UnInit(_,ty,id,_) ->
+ [(strip id,Ast0.ast0_type_to_type ty)]
+ | Ast0.MacroDecl(_,_,_,_,_) -> []
+ | Ast0.TyDecl(ty,_) -> []
+ | Ast0.Typedef(_,_,_,_) -> []
+ | Ast0.DisjDecl(_,disjs,_,_) ->
+ List.concat(List.map process_decl disjs)
+ | Ast0.Ddots(_,_) -> [] (* not in a statement list anyway *)
+ | Ast0.OptDecl(decl) -> process_decl decl
+ | Ast0.UniqueDecl(decl) -> process_decl decl in
+ let new_acc = (process_decl decl)@acc in
+ process_statement_list r new_acc ss
+ | Ast0.Dots(_,wc) ->
+ List.iter
+ (process_whencode r.V0.combiner_statement_dots
+ r.V0.combiner_statement)
+ wc;
+ process_statement_list r acc ss
+ | Ast0.Disj(_,statement_dots_list,_,_) ->
+ let new_acc =
+ lub_envs
+ (List.map
+ (function x -> process_statement_list r acc (Ast0.undots x))
+ statement_dots_list) in
+ process_statement_list r new_acc ss
+ | _ ->
+ let _ = (propagate_types acc).V0.combiner_statement s in
+ process_statement_list r acc ss) in
+
+ let statement_dots r k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ let _ = process_statement_list r env l in option_default in
+ let statement r k s =
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ let rec get_binding p =
+ match Ast0.unwrap p with
+ Ast0.Param(ty,Some id) ->
+ [(strip id,Ast0.ast0_type_to_type ty)]
+ | Ast0.OptParam(param) -> get_binding param
+ | _ -> [] in
+ let fenv = List.concat (List.map get_binding (Ast0.undots params)) in
+ (propagate_types (fenv@env)).V0.combiner_statement_dots body
+ | Ast0.IfThen(_,_,exp,_,_,_) | Ast0.IfThenElse(_,_,exp,_,_,_,_,_)
+ | Ast0.While(_,_,exp,_,_,_) | Ast0.Do(_,_,_,_,exp,_,_)
+ | Ast0.For(_,_,_,_,Some exp,_,_,_,_,_) | Ast0.Switch(_,_,exp,_,_,_,_) ->
+ let _ = k s in
+ let rec process_test exp =
+ match (Ast0.unwrap exp,Ast0.get_type exp) with
+ (Ast0.Edots(_,_),_) -> None
+ | (Ast0.NestExpr(_,_,_,_,_),_) -> None
+ | (Ast0.MetaExpr(_,_,_,_,_),_) ->
+ (* if a type is known, it is specified in the decl *)
+ None
+ | (Ast0.Paren(lp,exp,rp),None) -> process_test exp
+ | (_,None) -> Some (T.BaseType(T.IntType,None))
+ | _ -> None in
+ let new_expty = process_test exp in
+ (match new_expty with
+ None -> () (* leave things as they are *)
+ | Some ty -> Ast0.set_type exp new_expty);
+ None
+ | _ -> k s
+
+ and case_line r k c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) -> let _ = k c in None
+ | Ast0.Case(case,exp,colon,code) ->
+ let _ = k c in
+ (match Ast0.get_type exp with
+ None -> Ast0.set_type exp (Some (T.BaseType(T.IntType,None)))
+ | _ -> ());
+ None
+ | Ast0.OptCase(case) -> k c in
+
+ V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing statement_dots donothing donothing
+ ident expression donothing donothing donothing donothing statement
+ case_line donothing
+
+let type_infer code =
+ let prop = propagate_types [(Id("NULL"),T.Pointer(T.Unknown))] in
+ let fn = prop.V0.combiner_top_level in
+ let _ = List.map fn code in
+ ()
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* --------------------------------------------------------------------- *)
+(* Given two patterns, A and B, determine whether B can match any matched
+subterms of A. For simplicity, this doesn't maintain an environment; it
+just assume metavariables match. Thus the result is either NO or MAYBE. *)
+
+module Ast = Ast_cocci
+module V = Visitor_ast
+
+(* --------------------------------------------------------------------- *)
+
+type res = NO | MAYBE
+
+let return b = if b then MAYBE else NO
+
+let unify_mcode (x,_,_,_) (y,_,_,_) = x = y
+
+let unify_option f t1 t2 =
+ match (t1,t2) with
+ (Some t1, Some t2) -> f t1 t2
+ | (None, None) -> return true
+ | _ -> return false
+
+let unify_true_option f t1 t2 =
+ match (t1,t2) with
+ (Some t1, Some t2) -> f t1 t2
+ | (None, None) -> return true
+ | _ -> return true
+
+let bool_unify_option f t1 t2 =
+ match (t1,t2) with
+ (Some t1, Some t2) -> f t1 t2
+ | (None, None) -> true
+ | _ -> false
+
+let conjunct_bindings b1 b2 =
+ match b1 with NO -> b1 | MAYBE -> b2
+
+let disjunct_bindings b1 b2 =
+ match b1 with MAYBE -> b1 | NO -> b2
+
+let disjunct_all_bindings = List.fold_left disjunct_bindings NO
+
+(* --------------------------------------------------------------------- *)
+
+(* compute the common prefix. if in at least one case, this ends with the
+end of the pattern or a ..., then return true. *)
+
+let unify_lists fn dfn la lb =
+ let rec loop = function
+ ([],_) | (_,[]) -> return true
+ | (cura::resta,curb::restb) ->
+ (match fn cura curb with
+ MAYBE -> loop (resta,restb)
+ | NO -> if dfn cura or dfn curb then MAYBE else NO) in
+ loop (la,lb)
+
+let unify_dots fn dfn d1 d2 =
+ match (Ast.unwrap d1,Ast.unwrap d2) with
+ (Ast.DOTS(l1),Ast.DOTS(l2))
+ | (Ast.CIRCLES(l1),Ast.CIRCLES(l2))
+ | (Ast.STARS(l1),Ast.STARS(l2)) -> unify_lists fn dfn l1 l2
+ | _ -> return false
+
+let edots e =
+ match Ast.unwrap e with
+ Ast.Edots(_,_) | Ast.Ecircles(_,_) | Ast.Estars(_,_) -> true
+ | _ -> false
+
+let ddots e =
+ match Ast.unwrap e with
+ Ast.Ddots(_,_) -> true
+ | _ -> false
+
+let pdots p =
+ match Ast.unwrap p with
+ Ast.Pdots(_) | Ast.Pcircles(_) -> true
+ | _ -> false
+
+let dpdots e =
+ match Ast.unwrap e with
+ Ast.DPdots(_) | Ast.DPcircles(_) -> true
+ | _ -> false
+
+let sdots s =
+ match Ast.unwrap s with
+ Ast.Dots(_,_,_,_) | Ast.Circles(_,_,_,_) | Ast.Stars(_,_,_,_) -> true
+ | _ -> false
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+and unify_ident i1 i2 =
+ match (Ast.unwrap i1,Ast.unwrap i2) with
+ (Ast.Id(i1),Ast.Id(i2)) -> return (unify_mcode i1 i2)
+
+ | (Ast.MetaId(_,_,_,_),_)
+ | (Ast.MetaFunc(_,_,_,_),_)
+ | (Ast.MetaLocalFunc(_,_,_,_),_)
+ | (_,Ast.MetaId(_,_,_,_))
+ | (_,Ast.MetaFunc(_,_,_,_))
+ | (_,Ast.MetaLocalFunc(_,_,_,_)) -> return true
+
+ | (Ast.OptIdent(_),_)
+ | (Ast.UniqueIdent(_),_)
+ | (_,Ast.OptIdent(_))
+ | (_,Ast.UniqueIdent(_)) -> failwith "unsupported ident"
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let rec unify_expression e1 e2 =
+ match (Ast.unwrap e1,Ast.unwrap e2) with
+ (Ast.Ident(i1),Ast.Ident(i2)) -> unify_ident i1 i2
+ | (Ast.Constant(c1),Ast.Constant(c2))-> return (unify_mcode c1 c2)
+ | (Ast.FunCall(f1,lp1,args1,rp1),Ast.FunCall(f2,lp2,args2,rp2)) ->
+ conjunct_bindings
+ (unify_expression f1 f2)
+ (unify_dots unify_expression edots args1 args2)
+ | (Ast.Assignment(l1,op1,r1,_),Ast.Assignment(l2,op2,r2,_)) ->
+ if unify_mcode op1 op2
+ then conjunct_bindings (unify_expression l1 l2) (unify_expression r1 r2)
+ else return false
+ | (Ast.CondExpr(tst1,q1,thn1,c1,els1),Ast.CondExpr(tst2,q2,thn2,c2,els2)) ->
+ conjunct_bindings (unify_expression tst1 tst2)
+ (conjunct_bindings (unify_option unify_expression thn1 thn2)
+ (unify_expression els1 els2))
+ | (Ast.Postfix(e1,op1),Ast.Postfix(e2,op2)) ->
+ if unify_mcode op1 op2 then unify_expression e1 e2 else return false
+ | (Ast.Infix(e1,op1),Ast.Infix(e2,op2)) ->
+ if unify_mcode op1 op2 then unify_expression e1 e2 else return false
+ | (Ast.Unary(e1,op1),Ast.Unary(e2,op2)) ->
+ if unify_mcode op1 op2 then unify_expression e1 e2 else return false
+ | (Ast.Binary(l1,op1,r1),Ast.Binary(l2,op2,r2)) ->
+ if unify_mcode op1 op2
+ then conjunct_bindings (unify_expression l1 l2) (unify_expression r1 r2)
+ else return false
+ | (Ast.ArrayAccess(ar1,lb1,e1,rb1),Ast.ArrayAccess(ar2,lb2,e2,rb2)) ->
+ conjunct_bindings (unify_expression ar1 ar2) (unify_expression e1 e2)
+ | (Ast.RecordAccess(e1,d1,fld1),Ast.RecordAccess(e2,d2,fld2)) ->
+ conjunct_bindings (unify_expression e1 e2) (unify_ident fld1 fld2)
+ | (Ast.RecordPtAccess(e1,pt1,fld1),Ast.RecordPtAccess(e2,pt2,fld2)) ->
+ conjunct_bindings (unify_expression e1 e2) (unify_ident fld1 fld2)
+ | (Ast.Cast(lp1,ty1,rp1,e1),Ast.Cast(lp2,ty2,rp2,e2)) ->
+ conjunct_bindings (unify_fullType ty1 ty2) (unify_expression e1 e2)
+ | (Ast.SizeOfExpr(szf1,e1),Ast.SizeOfExpr(szf2,e2)) ->
+ unify_expression e1 e2
+ | (Ast.SizeOfType(szf1,lp1,ty1,rp1),Ast.SizeOfType(szf2,lp2,ty2,rp2)) ->
+ unify_fullType ty1 ty2
+ | (Ast.TypeExp(ty1),Ast.TypeExp(ty2)) -> unify_fullType ty1 ty2
+ | (Ast.Paren(lp1,e1,rp1),Ast.Paren(lp2,e2,rp2)) ->
+ unify_expression e1 e2
+
+ | (Ast.MetaErr(_,_,_,_),_)
+ | (Ast.MetaExpr(_,_,_,_,_,_),_)
+ | (Ast.MetaExprList(_,_,_,_),_)
+ | (_,Ast.MetaErr(_,_,_,_))
+ | (_,Ast.MetaExpr(_,_,_,_,_,_))
+ | (_,Ast.MetaExprList(_,_,_,_)) -> return true
+
+ | (Ast.EComma(cm1),Ast.EComma(cm2)) -> return true
+
+ | (Ast.DisjExpr(e1),_) ->
+ disjunct_all_bindings (List.map (function x -> unify_expression x e2) e1)
+ | (_,Ast.DisjExpr(e2)) ->
+ disjunct_all_bindings (List.map (function x -> unify_expression e1 x) e2)
+ | (Ast.NestExpr(e1,_,_),Ast.NestExpr(e2,_,_)) ->
+ unify_dots unify_expression edots e1 e2
+
+ (* dots can match against anything. return true to be safe. *)
+ | (Ast.Edots(_,_),_) | (_,Ast.Edots(_,_))
+ | (Ast.Ecircles(_,_),_) | (_,Ast.Ecircles(_,_))
+ | (Ast.Estars(_,_),_) | (_,Ast.Estars(_,_)) -> return true
+
+ | (Ast.OptExp(_),_)
+ | (Ast.UniqueExp(_),_)
+ | (_,Ast.OptExp(_))
+ | (_,Ast.UniqueExp(_)) -> failwith "unsupported expression"
+ | _ -> return false
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and unify_fullType ft1 ft2 =
+ match (Ast.unwrap ft1,Ast.unwrap ft2) with
+ (Ast.Type(cv1,ty1),Ast.Type(cv2,ty2)) ->
+ if bool_unify_option unify_mcode cv1 cv2
+ then unify_typeC ty1 ty2
+ else return false
+ | (Ast.DisjType(ft1),_) ->
+ disjunct_all_bindings (List.map (function x -> unify_fullType x ft2) ft1)
+ | (_,Ast.DisjType(ft2)) ->
+ disjunct_all_bindings (List.map (function x -> unify_fullType ft1 x) ft2)
+
+ | (Ast.OptType(_),_)
+ | (Ast.UniqueType(_),_)
+ | (_,Ast.OptType(_))
+ | (_,Ast.UniqueType(_)) -> failwith "unsupported type"
+
+and unify_typeC t1 t2 =
+ match (Ast.unwrap t1,Ast.unwrap t2) with
+ (Ast.BaseType(ty1,sgn1),Ast.BaseType(ty2,sgn2)) ->
+ return (unify_mcode ty1 ty2 && bool_unify_option unify_mcode sgn1 sgn2)
+ | (Ast.ImplicitInt(sgn1),Ast.ImplicitInt(sgn2)) ->
+ return (unify_mcode sgn1 sgn2)
+ | (Ast.Pointer(ty1,s1),Ast.Pointer(ty2,s2)) -> unify_fullType ty1 ty2
+ | (Ast.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a),
+ Ast.FunctionPointer(tyb,lp1b,starb,rp1b,lp2b,paramsb,rp2b)) ->
+ if List.for_all2 unify_mcode
+ [lp1a;stara;rp1a;lp2a;rp2a] [lp1b;starb;rp1b;lp2b;rp2b]
+ then
+ conjunct_bindings (unify_fullType tya tyb)
+ (unify_dots unify_parameterTypeDef pdots paramsa paramsb)
+ else return false
+ | (Ast.FunctionType(_,tya,lp1a,paramsa,rp1a),
+ Ast.FunctionType(_,tyb,lp1b,paramsb,rp1b)) ->
+ if List.for_all2 unify_mcode [lp1a;rp1a] [lp1b;rp1b]
+ then
+ conjunct_bindings (unify_option unify_fullType tya tyb)
+ (unify_dots unify_parameterTypeDef pdots paramsa paramsb)
+ else return false
+ | (Ast.FunctionType _ , _) -> failwith "not supported"
+ | (Ast.Array(ty1,lb1,e1,rb1),Ast.Array(ty2,lb2,e2,rb2)) ->
+ conjunct_bindings
+ (unify_fullType ty1 ty2) (unify_option unify_expression e1 e2)
+ | (Ast.StructUnionName(s1,Some ts1),Ast.StructUnionName(s2,Some ts2)) ->
+ if unify_mcode s1 s2 then unify_ident ts1 ts2 else return false
+ | (Ast.StructUnionName(s1,None),Ast.StructUnionName(s2,None)) ->
+ return true
+ | (Ast.StructUnionDef(ty1,lb1,decls1,rb1),
+ Ast.StructUnionDef(ty2,lb2,decls2,rb2)) ->
+ conjunct_bindings (unify_fullType ty1 ty2)
+ (unify_dots unify_declaration ddots decls1 decls2)
+ | (Ast.TypeName(t1),Ast.TypeName(t2)) -> return (unify_mcode t1 t2)
+
+ | (Ast.MetaType(_,_,_),_)
+ | (_,Ast.MetaType(_,_,_)) -> return true
+ | _ -> return false
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and unify_declaration d1 d2 =
+ match (Ast.unwrap d1,Ast.unwrap d2) with
+ (Ast.Init(stg1,ft1,id1,eq1,i1,s1),Ast.Init(stg2,ft2,id2,eq2,i2,s2)) ->
+ if bool_unify_option unify_mcode stg1 stg2
+ then
+ conjunct_bindings (unify_fullType ft1 ft2)
+ (conjunct_bindings (unify_ident id1 id2) (unify_initialiser i1 i2))
+ else return false
+ | (Ast.UnInit(stg1,ft1,id1,s1),Ast.UnInit(stg2,ft2,id2,s2)) ->
+ if bool_unify_option unify_mcode stg1 stg2
+ then conjunct_bindings (unify_fullType ft1 ft2) (unify_ident id1 id2)
+ else return false
+ | (Ast.MacroDecl(n1,lp1,args1,rp1,sem1),
+ Ast.MacroDecl(n2,lp2,args2,rp2,sem2)) ->
+ conjunct_bindings (unify_ident n1 n2)
+ (unify_dots unify_expression edots args1 args2)
+ | (Ast.TyDecl(ft1,s1),Ast.TyDecl(ft2,s2)) -> unify_fullType ft1 ft2
+ | (Ast.Typedef(stg1,ft1,id1,s1),Ast.Typedef(stg2,ft2,id2,s2)) ->
+ conjunct_bindings (unify_fullType ft1 ft2) (unify_typeC id1 id2)
+ | (Ast.DisjDecl(d1),_) ->
+ disjunct_all_bindings
+ (List.map (function x -> unify_declaration x d2) d1)
+ | (_,Ast.DisjDecl(d2)) ->
+ disjunct_all_bindings
+ (List.map (function x -> unify_declaration d1 x) d2)
+ (* dots can match against anything. return true to be safe. *)
+ | (Ast.Ddots(_,_),_) | (_,Ast.Ddots(_,_)) -> return true
+
+ | (Ast.OptDecl(_),_)
+ | (Ast.UniqueDecl(_),_)
+ | (_,Ast.OptDecl(_))
+ | (_,Ast.UniqueDecl(_)) -> failwith "unsupported decl"
+ | _ -> return false
+
+(* --------------------------------------------------------------------- *)
+(* Initializer *)
+
+and unify_initialiser i1 i2 =
+ match (Ast.unwrap i1,Ast.unwrap i2) with
+ (Ast.InitExpr(expa),Ast.InitExpr(expb)) ->
+ unify_expression expa expb
+ | (Ast.InitList(_,initlista,_,whena),
+ Ast.InitList(_,initlistb,_,whenb)) ->
+ (* ignore whencode - returns true safely *)
+ unify_lists unify_initialiser (function _ -> false) initlista initlistb
+ | (Ast.InitGccDotName(_,namea,_,inia),
+ Ast.InitGccDotName(_,nameb,_,inib)) ->
+ conjunct_bindings
+ (unify_ident namea nameb) (unify_initialiser inia inib)
+ | (Ast.InitGccName(namea,_,inia),Ast.InitGccName(nameb,_,inib)) ->
+ conjunct_bindings (unify_ident namea nameb) (unify_initialiser inia inib)
+ | (Ast.InitGccIndex(_,expa,_,_,inia),
+ Ast.InitGccIndex(_,expb,_,_,inib)) ->
+ conjunct_bindings
+ (unify_expression expa expb) (unify_initialiser inia inib)
+ | (Ast.InitGccRange(_,exp1a,_,exp2a,_,_,inia),
+ Ast.InitGccRange(_,exp1b,_,exp2b,_,_,inib)) ->
+ conjunct_bindings (unify_expression exp1a exp1b)
+ (conjunct_bindings (unify_expression exp2a exp2b)
+ (unify_initialiser inia inib))
+
+ | (Ast.OptIni(_),_)
+ | (Ast.UniqueIni(_),_)
+ | (_,Ast.OptIni(_))
+ | (_,Ast.UniqueIni(_)) -> failwith "unsupported decl"
+ | _ -> return false
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and unify_parameterTypeDef p1 p2 =
+ match (Ast.unwrap p1,Ast.unwrap p2) with
+ (Ast.VoidParam(ft1),Ast.VoidParam(ft2)) -> unify_fullType ft1 ft2
+ | (Ast.Param(ft1,i1),Ast.Param(ft2,i2)) ->
+ conjunct_bindings (unify_fullType ft1 ft2)
+ (unify_option unify_ident i1 i2)
+
+ | (Ast.MetaParam(_,_,_),_)
+ | (Ast.MetaParamList(_,_,_,_),_)
+ | (_,Ast.MetaParam(_,_,_))
+ | (_,Ast.MetaParamList(_,_,_,_)) -> return true
+
+ | (Ast.PComma(_),Ast.PComma(_)) -> return true
+
+ (* dots can match against anything. return true to be safe. *)
+ | (Ast.Pdots(_),_) | (_,Ast.Pdots(_))
+ | (Ast.Pcircles(_),_) | (_,Ast.Pcircles(_)) -> return true
+
+ | (Ast.OptParam(_),_)
+ | (Ast.UniqueParam(_),_)
+ | (_,Ast.OptParam(_))
+ | (_,Ast.UniqueParam(_)) -> failwith "unsupported parameter"
+ | _ -> return false
+
+(* --------------------------------------------------------------------- *)
+(* Define parameter *)
+
+and unify_define_parameters p1 p2 =
+ match (Ast.unwrap p1,Ast.unwrap p2) with
+ (Ast.NoParams,Ast.NoParams) -> return true
+ | (Ast.DParams(lp1,params1,rp1),Ast.DParams(lp2,params2,rp2)) ->
+ unify_dots unify_define_param dpdots params1 params2
+ | _ -> return false
+
+and unify_define_param p1 p2 =
+ match (Ast.unwrap p1,Ast.unwrap p2) with
+ (Ast.DParam(i1),Ast.DParam(i2)) ->
+ (unify_ident i1 i2)
+ | (Ast.DPComma(_),Ast.DPComma(_)) -> return true
+
+ (* dots can match against anything. return true to be safe. *)
+ | (Ast.DPdots(_),_) | (_,Ast.DPdots(_))
+ | (Ast.DPcircles(_),_) | (_,Ast.DPcircles(_)) -> return true
+
+ | (Ast.OptDParam(_),_)
+ | (Ast.UniqueDParam(_),_)
+ | (_,Ast.OptDParam(_))
+ | (_,Ast.UniqueDParam(_)) -> failwith "unsupported parameter"
+ | _ -> return false
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and unify_rule_elem re1 re2 =
+ match (Ast.unwrap re1,Ast.unwrap re2) with
+ (Ast.FunHeader(_,_,fi1,nm1,lp1,params1,rp1),
+ Ast.FunHeader(_,_,fi2,nm2,lp2,params2,rp2)) ->
+ conjunct_bindings (unify_fninfo fi1 fi2)
+ (conjunct_bindings (unify_ident nm1 nm2)
+ (unify_dots unify_parameterTypeDef pdots params1 params2))
+ | (Ast.Decl(_,_,d1),Ast.Decl(_,_,d2)) -> unify_declaration d1 d2
+
+ | (Ast.SeqStart(lb1),Ast.SeqStart(lb2)) -> return true
+ | (Ast.SeqEnd(rb1),Ast.SeqEnd(rb2)) -> return true
+
+ | (Ast.ExprStatement(e1,s1),Ast.ExprStatement(e2,s2)) ->
+ unify_expression e1 e2
+ | (Ast.IfHeader(if1,lp1,e1,rp1),Ast.IfHeader(if2,lp2,e2,rp2)) ->
+ unify_expression e1 e2
+ | (Ast.Else(e1),Ast.Else(e2)) -> return true
+ | (Ast.WhileHeader(wh1,lp1,e1,rp1),Ast.WhileHeader(wh2,lp2,e2,rp2)) ->
+ unify_expression e1 e2
+ | (Ast.DoHeader(d1),Ast.DoHeader(d2)) -> return true
+ | (Ast.WhileTail(wh1,lp1,e1,rp1,s1),Ast.WhileTail(wh2,lp2,e2,rp2,s2)) ->
+ unify_expression e1 e2
+ | (Ast.ForHeader(fr1,lp1,e11,s11,e21,s21,e31,rp1),
+ Ast.ForHeader(fr2,lp2,e12,s12,e22,s22,e32,rp2)) ->
+ conjunct_bindings
+ (unify_option unify_expression e11 e12)
+ (conjunct_bindings
+ (unify_option unify_expression e21 e22)
+ (unify_option unify_expression e31 e32))
+ | (Ast.IteratorHeader(nm1,lp1,args1,rp1),
+ Ast.IteratorHeader(nm2,lp2,args2,rp2)) ->
+ conjunct_bindings (unify_ident nm1 nm2)
+ (unify_dots unify_expression edots args1 args2)
+ | (Ast.DefineHeader(_,n1,p1),Ast.DefineHeader(_,n2,p2)) ->
+ conjunct_bindings (unify_ident n1 n2)
+ (unify_define_parameters p1 p2)
+ | (Ast.Break(r1,s1),Ast.Break(r2,s2)) -> return true
+ | (Ast.Continue(r1,s1),Ast.Continue(r2,s2)) -> return true
+ | (Ast.Label(l1,dd1),Ast.Label(l2,dd2)) -> unify_ident l1 l2
+ | (Ast.Goto(g1,l1,dd1),Ast.Goto(g2,l2,dd2)) -> unify_ident l1 l2
+ | (Ast.Return(r1,s1),Ast.Return(r2,s2)) -> return true
+ | (Ast.ReturnExpr(r1,e1,s1),Ast.ReturnExpr(r2,e2,s2)) ->
+ unify_expression e1 e2
+
+ | (Ast.DisjRuleElem(res1),_) ->
+ disjunct_all_bindings
+ (List.map (function x -> unify_rule_elem x re2) res1)
+ | (_,Ast.DisjRuleElem(res2)) ->
+ disjunct_all_bindings
+ (List.map (function x -> unify_rule_elem re1 x) res2)
+
+ | (Ast.MetaRuleElem(_,_,_),_)
+ | (Ast.MetaStmt(_,_,_,_),_)
+ | (Ast.MetaStmtList(_,_,_),_)
+ | (_,Ast.MetaRuleElem(_,_,_))
+ | (_,Ast.MetaStmt(_,_,_,_))
+ | (_,Ast.MetaStmtList(_,_,_)) -> return true
+
+ (* can match a rule_elem in different parts *)
+ | (Ast.Exp(e1),Ast.Exp(e2)) -> return true
+ | (Ast.Exp(e1),_) -> subexp (unify_expression e1) re2
+ | (_,Ast.Exp(e2)) -> subexp (unify_expression e2) re1
+
+ | (Ast.TopExp(e1),Ast.TopExp(e2)) -> unify_expression e1 e2
+
+ (* can match a rule_elem in different parts *)
+ | (Ast.Ty(t1),Ast.Ty(t2)) -> return true
+ | (Ast.Ty(t1),_) -> subtype (unify_fullType t1) re2
+ | (_,Ast.Ty(t2)) -> subtype (unify_fullType t2) re1
+ | _ -> return false
+
+and unify_fninfo patterninfo cinfo =
+ let patterninfo = List.sort compare patterninfo in
+ let cinfo = List.sort compare cinfo in
+ let rec loop = function
+ (Ast.FStorage(sta)::resta,Ast.FStorage(stb)::restb) ->
+ if unify_mcode sta stb then loop (resta,restb) else return false
+ | (Ast.FType(tya)::resta,Ast.FType(tyb)::restb) ->
+ conjunct_bindings (unify_fullType tya tyb) (loop (resta,restb))
+ | (Ast.FInline(ia)::resta,Ast.FInline(ib)::restb) ->
+ if unify_mcode ia ib then loop (resta,restb) else return false
+ | (Ast.FAttr(ia)::resta,Ast.FAttr(ib)::restb) ->
+ if unify_mcode ia ib then loop (resta,restb) else return false
+ | (x::resta,((y::_) as restb)) ->
+ (match compare x y with
+ -1 -> return false
+ | 1 -> loop (resta,restb)
+ | _ -> failwith "not possible")
+ | _ -> return false in
+ loop (patterninfo,cinfo)
+
+and subexp f =
+ let bind = conjunct_bindings in
+ let option_default = return false in
+ let mcode r e = option_default in
+ let expr r k e = conjunct_bindings (f e) (k e) in
+ let donothing r k e = k e in
+ let recursor = V.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing
+ donothing expr donothing donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing in
+ recursor.V.combiner_rule_elem
+
+and subtype f =
+ let bind = conjunct_bindings in
+ let option_default = return false in
+ let mcode r e = option_default in
+ let fullType r k e = conjunct_bindings (f e) (k e) in
+ let donothing r k e = k e in
+ let recursor = V.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing
+ donothing donothing fullType donothing donothing donothing donothing
+ donothing donothing donothing donothing donothing in
+ recursor.V.combiner_rule_elem
+
+let rec unify_statement s1 s2 =
+ match (Ast.unwrap s1,Ast.unwrap s2) with
+ (Ast.Seq(lb1,d1,s1,rb1),Ast.Seq(lb2,d2,s2,rb2)) ->
+ conjunct_bindings (unify_rule_elem lb1 lb2)
+ (conjunct_bindings
+ (unify_dots unify_statement sdots s1 s2)
+ (conjunct_bindings
+ (unify_dots unify_statement sdots d1 d2)
+ (unify_rule_elem rb1 rb2)))
+ | (Ast.IfThen(h1,thn1,_),Ast.IfThen(h2,thn2,_)) ->
+ conjunct_bindings (unify_rule_elem h1 h2) (unify_statement thn1 thn2)
+ | (Ast.IfThenElse(h1,thn1,e1,els1,_),Ast.IfThenElse(h2,thn2,e2,els2,_)) ->
+ conjunct_bindings (unify_rule_elem h1 h2)
+ (conjunct_bindings (unify_statement thn1 thn2)
+ (conjunct_bindings (unify_rule_elem e1 e2)
+ (unify_statement els1 els2)))
+ | (Ast.While(h1,s1,_),Ast.While(h2,s2,_)) ->
+ conjunct_bindings (unify_rule_elem h1 h2) (unify_statement s1 s2)
+ | (Ast.Do(h1,s1,t1),Ast.Do(h2,s2,t2)) ->
+ conjunct_bindings (unify_rule_elem h1 h2)
+ (conjunct_bindings (unify_statement s1 s2) (unify_rule_elem t1 t2))
+ | (Ast.For(h1,s1,_),Ast.For(h2,s2,_)) ->
+ conjunct_bindings (unify_rule_elem h1 h2) (unify_statement s1 s2)
+ | (Ast.Atomic(re1),Ast.Atomic(re2)) -> unify_rule_elem re1 re2
+ | (Ast.Disj(s1),_) ->
+ let s2 = Ast.rewrap s2 (Ast.DOTS[s2]) in
+ disjunct_all_bindings
+ (List.map
+ (function x -> unify_dots unify_statement sdots x s2)
+ s1)
+ | (_,Ast.Disj(s2)) ->
+ let s1 = Ast.rewrap s1 (Ast.DOTS[s1]) in
+ disjunct_all_bindings
+ (List.map
+ (function x -> unify_dots unify_statement sdots s1 x)
+ s2)
+ | (Ast.Nest(s1,_,_,_,_),Ast.Nest(s2,_,_,_,_)) ->
+ unify_dots unify_statement sdots s1 s2
+ | (Ast.FunDecl(h1,lb1,d1,s1,rb1),Ast.FunDecl(h2,lb2,d2,s2,rb2)) ->
+ conjunct_bindings (unify_rule_elem h1 h2)
+ (conjunct_bindings (unify_rule_elem lb1 lb2)
+ (conjunct_bindings (unify_dots unify_statement sdots d1 d2)
+ (conjunct_bindings (unify_dots unify_statement sdots s1 s2)
+ (unify_rule_elem rb1 rb2))))
+ | (Ast.Define(h1,s1),Ast.Define(h2,s2)) ->
+ conjunct_bindings (unify_rule_elem h1 h2)
+ (unify_dots unify_statement sdots s1 s2)
+ (* dots can match against anything. return true to be safe. *)
+ | (Ast.Dots(_,_,_,_),_) | (_,Ast.Dots(_,_,_,_))
+ | (Ast.Circles(_,_,_,_),_) | (_,Ast.Circles(_,_,_,_))
+ | (Ast.Stars(_,_,_,_),_) | (_,Ast.Stars(_,_,_,_)) -> return true
+ | (Ast.OptStm(_),_)
+ | (Ast.UniqueStm(_),_)
+ | (_,Ast.OptStm(_))
+ | (_,Ast.UniqueStm(_)) -> failwith "unsupported statement"
+ | _ -> return false
+
+let unify_statement_dots = unify_dots unify_statement sdots
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+(* find unitary metavariables *)
+module Ast0 = Ast0_cocci
+module Ast = Ast_cocci
+module V0 = Visitor_ast0
+
+let set_minus s minus = List.filter (function n -> not (List.mem n minus)) s
+
+let rec nub = function
+ [] -> []
+ | (x::xs) when (List.mem x xs) -> nub xs
+ | (x::xs) -> x::(nub xs)
+
+(* ----------------------------------------------------------------------- *)
+(* Find the variables that occur free and occur free in a unitary way *)
+
+(* take everything *)
+let minus_checker name = let id = Ast0.unwrap_mcode name in [id]
+
+(* take only what is in the plus code *)
+let plus_checker (nm,_,_,mc,_) =
+ match mc with Ast0.PLUS -> [nm] | _ -> []
+
+let get_free checker t =
+ let bind x y = x @ y in
+ let option_default = [] in
+ let donothing r k e = k e in
+ let mcode _ = option_default in
+
+ (* considers a single list *)
+ let collect_unitary_nonunitary free_usage =
+ let free_usage = List.sort compare free_usage in
+ let rec loop1 todrop = function
+ [] -> []
+ | (x::xs) as all -> if x = todrop then loop1 todrop xs else all in
+ let rec loop2 = function
+ [] -> ([],[])
+ | [x] -> ([x],[])
+ | x::y::xs ->
+ if x = y
+ then
+ let (unitary,non_unitary) = loop2(loop1 x xs) in
+ (unitary,x::non_unitary)
+ else
+ let (unitary,non_unitary) = loop2 (y::xs) in
+ (x::unitary,non_unitary) in
+ loop2 free_usage in
+
+ (* considers a list of lists *)
+ let detect_unitary_frees l =
+ let (unitary,nonunitary) =
+ List.split (List.map collect_unitary_nonunitary l) in
+ let unitary = nub (List.concat unitary) in
+ let nonunitary = nub (List.concat nonunitary) in
+ let unitary =
+ List.filter (function x -> not (List.mem x nonunitary)) unitary in
+ unitary@nonunitary@nonunitary in
+
+ let whencode afn bfn = function
+ Ast0.WhenNot(a) -> afn a
+ | Ast0.WhenAlways(b) -> bfn b
+ | Ast0.WhenModifier(_) -> option_default in
+
+ let ident r k i =
+ match Ast0.unwrap i with
+ Ast0.MetaId(name,_,_) | Ast0.MetaFunc(name,_,_)
+ | Ast0.MetaLocalFunc(name,_,_) -> checker name
+ | _ -> k i in
+
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.MetaErr(name,_,_) | Ast0.MetaExpr(name,_,_,_,_)
+ | Ast0.MetaExprList(name,_,_) -> checker name
+ | Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ detect_unitary_frees(List.map r.V0.combiner_expression expr_list)
+ | _ -> k e in
+
+ let typeC r k t =
+ match Ast0.unwrap t with
+ Ast0.MetaType(name,_) -> checker name
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ detect_unitary_frees(List.map r.V0.combiner_typeC types)
+ | _ -> k t in
+
+ let parameter r k p =
+ match Ast0.unwrap p with
+ Ast0.MetaParam(name,_) | Ast0.MetaParamList(name,_,_) -> checker name
+ | _ -> k p in
+
+ let declaration r k d =
+ match Ast0.unwrap d with
+ Ast0.DisjDecl(starter,decls,mids,ender) ->
+ detect_unitary_frees(List.map r.V0.combiner_declaration decls)
+ | _ -> k d in
+
+ let statement r k s =
+ match Ast0.unwrap s with
+ Ast0.MetaStmt(name,_) | Ast0.MetaStmtList(name,_) -> checker name
+ | Ast0.Disj(starter,stmt_list,mids,ender) ->
+ detect_unitary_frees(List.map r.V0.combiner_statement_dots stmt_list)
+ | Ast0.Nest(starter,stmt_dots,ender,whn,multi) ->
+ bind (r.V0.combiner_statement_dots stmt_dots)
+ (detect_unitary_frees
+ (List.map
+ (whencode r.V0.combiner_statement_dots r.V0.combiner_statement)
+ whn))
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
+ detect_unitary_frees
+ (List.map
+ (whencode r.V0.combiner_statement_dots r.V0.combiner_statement)
+ whn)
+ | _ -> k s in
+
+ let res = V0.combiner bind option_default
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ ident expression typeC donothing parameter declaration statement
+ donothing donothing in
+
+ collect_unitary_nonunitary
+ (List.concat (List.map res.V0.combiner_top_level t))
+
+(* ----------------------------------------------------------------------- *)
+(* update the variables that are unitary *)
+
+let update_unitary unitary =
+ let donothing r k e = k e in
+ let mcode x = x in
+
+ let is_unitary name =
+ match (List.mem (Ast0.unwrap_mcode name) unitary,
+ Ast0.get_mcode_mcodekind name) with
+ (true,Ast0.CONTEXT(mc)) -> Ast0.PureContext
+ | (true,_) -> Ast0.Pure
+ | (false,Ast0.CONTEXT(mc)) -> Ast0.Context
+ | (false,_) -> Ast0.Impure in
+
+ let ident r k i =
+ match Ast0.unwrap i with
+ Ast0.MetaId(name,constraints,_) ->
+ Ast0.rewrap i (Ast0.MetaId(name,constraints,is_unitary name))
+ | Ast0.MetaFunc(name,constraints,_) ->
+ Ast0.rewrap i (Ast0.MetaFunc(name,constraints,is_unitary name))
+ | Ast0.MetaLocalFunc(name,constraints,_) ->
+ Ast0.rewrap i (Ast0.MetaLocalFunc(name,constraints,is_unitary name))
+ | _ -> k i in
+
+ let expression r k e =
+ match Ast0.unwrap e with
+ Ast0.MetaErr(name,constraints,_) ->
+ Ast0.rewrap e (Ast0.MetaErr(name,constraints,is_unitary name))
+ | Ast0.MetaExpr(name,constraints,ty,form,_) ->
+ Ast0.rewrap e (Ast0.MetaExpr(name,constraints,ty,form,is_unitary name))
+ | Ast0.MetaExprList(name,lenname,_) ->
+ Ast0.rewrap e (Ast0.MetaExprList(name,lenname,is_unitary name))
+ | _ -> k e in
+
+ let typeC r k t =
+ match Ast0.unwrap t with
+ Ast0.MetaType(name,_) ->
+ Ast0.rewrap t (Ast0.MetaType(name,is_unitary name))
+ | _ -> k t in
+
+ let parameter r k p =
+ match Ast0.unwrap p with
+ Ast0.MetaParam(name,_) ->
+ Ast0.rewrap p (Ast0.MetaParam(name,is_unitary name))
+ | Ast0.MetaParamList(name,lenname,_) ->
+ Ast0.rewrap p (Ast0.MetaParamList(name,lenname,is_unitary name))
+ | _ -> k p in
+
+ let statement r k s =
+ match Ast0.unwrap s with
+ Ast0.MetaStmt(name,_) ->
+ Ast0.rewrap s (Ast0.MetaStmt(name,is_unitary name))
+ | Ast0.MetaStmtList(name,_) ->
+ Ast0.rewrap s (Ast0.MetaStmtList(name,is_unitary name))
+ | _ -> k s in
+
+ let res = V0.rebuilder
+ mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
+ mcode
+ donothing donothing donothing donothing donothing donothing
+ ident expression typeC donothing parameter donothing statement
+ donothing donothing in
+
+ List.map res.V0.rebuilder_top_level
+
+(* ----------------------------------------------------------------------- *)
+
+let rec split3 = function
+ [] -> ([],[],[])
+ | (a,b,c)::xs -> let (l1,l2,l3) = split3 xs in (a::l1,b::l2,c::l3)
+
+let rec combine3 = function
+ ([],[],[]) -> []
+ | (a::l1,b::l2,c::l3) -> (a,b,c) :: combine3 (l1,l2,l3)
+ | _ -> failwith "not possible"
+
+(* ----------------------------------------------------------------------- *)
+(* process all rules *)
+
+let do_unitary rules =
+ let rec loop = function
+ [] -> ([],[])
+ | (r::rules) ->
+ match r with
+ Ast0.ScriptRule (a,b,c,d) ->
+ let (x,rules) = loop rules in
+ (x, r::rules)
+ | Ast0.CocciRule ((minus,metavars,chosen_isos),((plus,_) as plusz)) ->
+ let mm1 = List.map Ast.get_meta_name metavars in
+ let (used_after, rest) = loop rules in
+ let (m_unitary, m_nonunitary) = get_free minus_checker minus in
+ let (p_unitary, p_nonunitary) = get_free plus_checker plus in
+ let p_free =
+ if !Flag.sgrep_mode2 then []
+ else p_unitary @ p_nonunitary in
+ let (in_p, m_unitary) =
+ List.partition (function x -> List.mem x p_free) m_unitary in
+ let m_nonunitary = in_p @ m_nonunitary in
+ let (m_unitary, not_local) =
+ List.partition (function x -> List.mem x mm1) m_unitary in
+ let m_unitary =
+ List.filter (function x -> not (List.mem x used_after))
+ m_unitary in
+ let rebuilt = update_unitary m_unitary minus in
+ (set_minus (m_nonunitary @ used_after) mm1,
+ (Ast0.CocciRule
+ ((rebuilt, metavars, chosen_isos),plusz))::rest) in
+ let (_,rules) = loop rules in
+ rules
+
+(*
+let do_unitary minus plus =
+ let (minus,metavars,chosen_isos) = split3 minus in
+ let (plus,_) = List.split plus in
+ let rec loop = function
+ ([],[],[]) -> ([],[])
+ | (mm1::metavars,m1::minus,p1::plus) ->
+ let mm1 = List.map Ast.get_meta_name mm1 in
+ let (used_after,rest) = loop (metavars,minus,plus) in
+ let (m_unitary,m_nonunitary) = get_free minus_checker m1 in
+ let (p_unitary,p_nonunitary) = get_free plus_checker p1 in
+ let p_free =
+ if !Flag.sgrep_mode2
+ then []
+ else p_unitary @ p_nonunitary in
+ let (in_p,m_unitary) =
+ List.partition (function x -> List.mem x p_free) m_unitary in
+ let m_nonunitary = in_p@m_nonunitary in
+ let (m_unitary,not_local) =
+ List.partition (function x -> List.mem x mm1) m_unitary in
+ let m_unitary =
+ List.filter (function x -> not(List.mem x used_after)) m_unitary in
+ let rebuilt = update_unitary m_unitary m1 in
+ (set_minus (m_nonunitary @ used_after) mm1,
+ rebuilt::rest)
+ | _ -> failwith "not possible" in
+ let (_,rules) = loop (metavars,minus,plus) in
+ combine3 (rules,metavars,chosen_isos)
+*)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Format
+module Ast0 = Ast0_cocci
+module U = Pretty_print_cocci
+
+let quiet = ref true (* true = no decoration on - context, etc *)
+
+let start_block str =
+ force_newline(); print_string " "; open_box 0
+
+let end_block str =
+ close_box(); force_newline ()
+
+let print_option = Common.do_option
+let print_between = Common.print_between
+
+(* --------------------------------------------------------------------- *)
+(* Positions *)
+
+let meta_pos = function
+ Ast0.MetaPos(name,_,_) ->
+ print_string "@";
+ let (_,name) = Ast0.unwrap_mcode name in
+ print_string name
+ | Ast0.NoMetaPos -> ()
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+let mcodekind brackets fn x info = function
+ Ast0.MINUS(plus_stream) ->
+ let (lb,rb) =
+ if !quiet
+ then ("","")
+ else
+ match brackets with
+ Some x -> ("[","]^"^(string_of_int x))
+ | None -> ("","") in
+ let (plus_stream,_) = !plus_stream in
+ if !quiet
+ then fn x
+ else (print_string "-";
+ print_string lb; fn x; print_string rb);
+ U.print_anything ">>> " plus_stream
+ | Ast0.CONTEXT(plus_streams) ->
+ let (lb,rb) =
+ if !quiet
+ then ("","")
+ else
+ match brackets with
+ Some x -> ("[",("]^"^(string_of_int x))) | None -> ("","") in
+ let (plus_streams,t1,t2) = !plus_streams in
+ U.print_around
+ (function x ->
+ print_string lb; fn x; print_string rb)
+ x plus_streams
+ | Ast0.PLUS ->
+ List.iter (function s -> print_string s; force_newline())
+ info.Ast0.strings_before;
+ fn x;
+ List.iter (function s -> force_newline(); print_string s)
+ info.Ast0.strings_after
+ | Ast0.MIXED(plus_streams) ->
+ let (lb,rb) =
+ if !quiet
+ then ("","")
+ else
+ let n =
+ match brackets with Some x -> "^"^(string_of_int x) | None -> "" in
+ ("§","½"^n) in
+ let (plus_streams,_,_) = !plus_streams in
+ U.print_around (function x -> print_string lb; fn x; print_string rb)
+ x plus_streams
+
+let mcode fn (x,_,info,mc,pos) =
+ let fn x = fn x; meta_pos !pos in
+ mcodekind (Some info.Ast0.line_start)(*None*) fn x info mc
+
+let print_context x fn =
+ mcodekind (Some (Ast0.get_line x)) fn () (Ast0.get_info x)
+ (Ast0.get_mcodekind x)
+
+let print_meta (_,name) = print_string name
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots between fn d =
+ print_context d
+ (function _ ->
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> print_between between fn l
+ | Ast0.CIRCLES(l) -> print_between between fn l
+ | Ast0.STARS(l) -> print_between between fn l)
+
+(* --------------------------------------------------------------------- *)
+
+let print_types = function
+ None -> ()
+ | Some ty ->
+ print_string "/* ";
+ Format.print_flush();
+ print_between (function _ -> print_string ", ") Type_cocci.typeC ty;
+ Format.print_flush();
+ print_string " */"
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let rec ident i =
+ print_context i
+ (function _ ->
+ match Ast0.unwrap i with
+ Ast0.Id(name) -> mcode print_string name
+ | Ast0.MetaId(name,_,_) -> mcode print_meta name
+ | Ast0.MetaFunc(name,_,_) -> mcode print_meta name
+ | Ast0.MetaLocalFunc(name,_,_) -> mcode print_meta name
+ | Ast0.OptIdent(id) -> print_string "?"; ident id
+ | Ast0.UniqueIdent(id) -> print_string "!"; ident id)
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let print_string_box s = print_string s; open_box 0
+
+let rec expression e =
+ print_option Type_cocci.typeC (Ast0.get_type e);
+ print_context e
+ (function _ ->
+ match Ast0.unwrap e with
+ Ast0.Ident(id) -> ident id
+ | Ast0.Constant(const) -> mcode U.constant const
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ expression fn; mcode print_string_box lp;
+ let _ = dots (function _ -> ()) expression args in
+ close_box(); mcode print_string rp
+ | Ast0.Assignment(left,op,right,_) ->
+ expression left; print_string " "; mcode U.assignOp op;
+ print_string " "; expression right
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ expression exp1; print_string " "; mcode print_string why;
+ print_option (function e -> print_string " "; expression e) exp2;
+ print_string " "; mcode print_string colon; expression exp3
+ | Ast0.Postfix(exp,op) -> expression exp; mcode U.fixOp op
+ | Ast0.Infix(exp,op) -> mcode U.fixOp op; expression exp
+ | Ast0.Unary(exp,op) -> mcode U.unaryOp op; expression exp
+ | Ast0.Binary(left,op,right) ->
+ print_string "(";
+ expression left; print_string " "; mcode U.binaryOp op;
+ print_string " "; expression right;
+ print_string ")"
+ | Ast0.Nested(left,op,right) ->
+ print_string "(";
+ expression left; print_string " "; mcode U.binaryOp op;
+ print_string " "; expression right;
+ print_string ")"
+ | Ast0.Paren(lp,exp,rp) ->
+ mcode print_string_box lp; expression exp; close_box();
+ mcode print_string rp
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ expression exp1; mcode print_string_box lb; expression exp2;
+ close_box(); mcode print_string rb
+ | Ast0.RecordAccess(exp,pt,field) ->
+ expression exp; mcode print_string pt; ident field
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ expression exp; mcode print_string ar; ident field
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ mcode print_string_box lp; typeC ty; close_box();
+ mcode print_string rp; expression exp
+ | Ast0.SizeOfExpr(szf,exp) ->
+ mcode print_string szf; expression exp
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ mcode print_string szf;
+ mcode print_string_box lp; typeC ty; close_box();
+ mcode print_string rp
+ | Ast0.TypeExp(ty) -> typeC ty
+ | Ast0.MetaErr(name,_,_) -> mcode print_meta name
+ | Ast0.MetaExpr(name,_,ty,_,_) ->
+ mcode print_meta name; print_types ty
+ | Ast0.MetaExprList(name,_,_) -> mcode print_meta name
+ | Ast0.EComma(cm) -> mcode print_string cm; print_space()
+ | Ast0.DisjExpr(_,exp_list,_,_) ->
+ print_string "\n("; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ expression exp_list;
+ print_string "\n)"
+ | Ast0.NestExpr(starter,expr_dots,ender,None,multi) ->
+ mcode print_string starter;
+ start_block(); dots force_newline expression expr_dots; end_block();
+ mcode print_string ender
+ | Ast0.NestExpr(starter,expr_dots,ender,Some whencode,multi) ->
+ mcode print_string starter; print_string " WHEN != ";
+ expression whencode;
+ start_block(); dots force_newline expression expr_dots; end_block();
+ mcode print_string ender
+ | Ast0.Edots(dots,Some whencode)
+ | Ast0.Ecircles(dots,Some whencode)
+ | Ast0.Estars(dots,Some whencode) ->
+ mcode print_string dots; print_string " WHEN != ";
+ expression whencode
+ | Ast0.Edots(dots,None)
+ | Ast0.Ecircles(dots,None)
+ | Ast0.Estars(dots,None) -> mcode print_string dots
+ | Ast0.OptExp(exp) -> print_string "?"; expression exp
+ | Ast0.UniqueExp(exp) -> print_string "!"; expression exp)
+
+and expression_dots x = dots (function _ -> ()) expression x
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2) fn =
+ typeC ty; mcode print_string lp1; mcode print_string star; fn();
+ mcode print_string rp1; mcode print_string lp2;
+ parameter_list params; mcode print_string rp2
+
+and print_function_type (ty,lp1,params,rp1) fn =
+ print_option typeC ty; fn(); mcode print_string lp1;
+ parameter_list params; mcode print_string rp1
+
+and typeC t =
+ print_context t
+ (function _ ->
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) ->
+ mcode U.const_vol cv; print_string " "; typeC ty
+ | Ast0.BaseType(ty,sgn) ->
+ print_option (mcode U.sign) sgn; mcode U.baseType ty
+ | Ast0.ImplicitInt(sgn) -> mcode U.sign sgn
+ | Ast0.Pointer(ty,star) -> typeC ty; mcode print_string star
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> ())
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1) (function _ -> ())
+ | Ast0.Array(ty,lb,size,rb) ->
+ typeC ty; mcode print_string lb; print_option expression size;
+ mcode print_string rb
+ | Ast0.StructUnionName(kind,name) ->
+ mcode U.structUnion kind;
+ print_option (function x -> ident x; print_string " ") name
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ typeC ty; mcode print_string lb;
+ dots force_newline declaration decls;
+ mcode print_string rb
+ | Ast0.TypeName(name)-> mcode print_string name; print_string " "
+ | Ast0.MetaType(name,_)-> mcode print_meta name; print_string " "
+ | Ast0.DisjType(lp,types,mids,rp) ->
+ print_string "\n"; mcode print_string lp; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ typeC types;
+ print_string "\n"; mcode print_string rp
+ | Ast0.OptType(ty) -> print_string "?"; typeC ty
+ | Ast0.UniqueType(ty) -> print_string "!"; typeC ty)
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and print_named_type ty id =
+ match Ast0.unwrap ty with
+ Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> print_string " "; ident id)
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1)
+ (function _ -> print_string " "; ident id)
+ | Ast0.Array(ty,lb,size,rb) ->
+ let rec loop ty k =
+ match Ast0.unwrap ty with
+ Ast0.Array(ty,lb,size,rb) ->
+ loop ty
+ (function _ ->
+ k ();
+ mcode print_string lb;
+ print_option expression size;
+ mcode print_string rb)
+ | _ -> typeC ty; ident id; k () in
+ loop ty (function _ -> ())
+ | _ -> typeC ty; ident id
+
+and declaration d =
+ print_context d
+ (function _ ->
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ print_option (mcode U.storage) stg;
+ print_named_type ty id;
+ print_string " ";
+ mcode print_string eq; print_string " "; initialiser ini;
+ mcode print_string sem
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ print_option (mcode U.storage) stg; print_named_type ty id;
+ mcode print_string sem
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ ident name; mcode print_string_box lp;
+ let _ = dots (function _ -> ()) expression args in
+ close_box(); mcode print_string rp; mcode print_string sem
+ | Ast0.TyDecl(ty,sem) -> typeC ty; mcode print_string sem
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ mcode print_string stg; typeC ty; typeC id;
+ mcode print_string sem
+ | Ast0.DisjDecl(_,decls,_,_) ->
+ print_string "\n("; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ declaration decls;
+ print_string "\n)"
+ | Ast0.Ddots(dots,Some whencode) ->
+ mcode print_string dots; print_string " when != ";
+ declaration whencode
+ | Ast0.Ddots(dots,None) -> mcode print_string dots
+ | Ast0.OptDecl(decl) -> print_string "?"; declaration decl
+ | Ast0.UniqueDecl(decl) -> print_string "!"; declaration decl)
+
+and declaration_dots l = dots (function _ -> ()) declaration l
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and initialiser i =
+ print_context i
+ (function _ ->
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> expression exp
+ | Ast0.InitList(lb,initlist,rb) ->
+ mcode print_string lb; open_box 0;
+ let _ = dots (function _ -> ()) initialiser initlist in
+ close_box(); mcode print_string rb
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ mcode print_string dot; ident name; print_string " ";
+ mcode print_string eq; print_string " "; initialiser ini
+ | Ast0.InitGccName(name,eq,ini) ->
+ ident name; mcode print_string eq; initialiser ini
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ mcode print_string lb; expression exp; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ mcode print_string lb; expression exp1; mcode print_string dots;
+ expression exp2; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast0.IComma(cm) -> mcode print_string cm; force_newline()
+ | Ast0.Idots(d,Some whencode) ->
+ mcode print_string d; print_string " WHEN != ";
+ initialiser whencode
+ | Ast0.Idots(d,None) -> mcode print_string d
+ | Ast0.OptIni(ini) -> print_string "?"; initialiser ini
+ | Ast0.UniqueIni(ini) -> print_string "!"; initialiser ini)
+
+and initialiser_list l = dots (function _ -> ()) initialiser l
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef p =
+ print_context p
+ (function _ ->
+ match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> typeC ty
+ | Ast0.Param(ty,Some id) -> print_named_type ty id
+ | Ast0.Param(ty,None) -> typeC ty
+ | Ast0.MetaParam(name,_) -> mcode print_meta name
+ | Ast0.MetaParamList(name,_,_) -> mcode print_meta name
+ | Ast0.PComma(cm) -> mcode print_string cm; print_space()
+ | Ast0.Pdots(dots) -> mcode print_string dots
+ | Ast0.Pcircles(dots) -> mcode print_string dots
+ | Ast0.OptParam(param) -> print_string "?"; parameterTypeDef param
+ | Ast0.UniqueParam(param) -> print_string "!"; parameterTypeDef param)
+
+and parameter_list l = dots (function _ -> ()) parameterTypeDef l
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and statement arity s =
+ print_context s
+ (function _ ->
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ print_string arity;
+ List.iter print_fninfo fninfo;
+ ident name; mcode print_string_box lp;
+ parameter_list params; close_box(); mcode print_string rp;
+ print_string " ";
+ print_string arity; mcode print_string lbrace; start_block();
+ dots force_newline (statement arity) body;
+ end_block(); print_string arity; mcode print_string rbrace
+ | Ast0.Decl(_,decl) -> print_string arity; declaration decl
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ print_string arity; mcode print_string lbrace; start_block();
+ dots force_newline (statement arity) body;
+ end_block(); print_string arity; mcode print_string rbrace
+ | Ast0.ExprStatement(exp,sem) ->
+ print_string arity; expression exp; mcode print_string sem
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) ->
+ print_string arity;
+ mcode print_string iff; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " ";
+ statement arity branch1;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
+ print_string arity;
+ mcode print_string iff; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " ";
+ statement arity branch1;
+ print_string arity; mcode print_string els; print_string " ";
+ statement arity branch2;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.While(whl,lp,exp,rp,body,(info,aft)) ->
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " ";
+ statement arity body;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
+ print_string arity; mcode print_string d; print_string " ";
+ statement arity body;
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp;
+ mcode print_string sem
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
+ print_string arity;
+ mcode print_string fr; mcode print_string_box lp;
+ print_option expression e1; mcode print_string sem1;
+ print_option expression e2; mcode print_string sem2;
+ print_option expression e3; close_box();
+ mcode print_string rp; print_string " "; statement arity body;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) ->
+ print_string arity;
+ ident nm; print_string " "; mcode print_string_box lp;
+ let _ = dots (function _ -> ()) expression args in
+ close_box(); mcode print_string rp; print_string " ";
+ statement arity body;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ print_string arity;
+ mcode print_string switch; print_string " ";
+ mcode print_string_box lp; expression exp; close_box();
+ mcode print_string rp; print_string " "; mcode print_string lb;
+ dots force_newline (case_line arity) cases;
+ mcode print_string rb
+ | Ast0.Break(br,sem) ->
+ print_string arity; mcode print_string br; mcode print_string sem
+ | Ast0.Continue(cont,sem) ->
+ print_string arity; mcode print_string cont; mcode print_string sem
+ | Ast0.Label(l,dd) -> ident l; print_string ":"
+ | Ast0.Goto(goto,l,sem) ->
+ mcode print_string goto; ident l; mcode print_string sem
+ | Ast0.Return(ret,sem) ->
+ print_string arity; mcode print_string ret; mcode print_string sem
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ print_string arity; mcode print_string ret; print_string " ";
+ expression exp; mcode print_string sem
+ | Ast0.MetaStmt(name,pure) ->
+ print_string arity; mcode print_meta name;(*
+ print_string "^";
+ (match pure with
+ Ast0.Pure -> print_string "pure"
+ | Ast0.Impure -> print_string "impure"
+ | Ast0.Context -> print_string "context"
+ | Ast0.PureContext -> print_string "pure_context")*)
+ | Ast0.MetaStmtList(name,_) ->
+ print_string arity; mcode print_meta name
+ | Ast0.Disj(_,statement_dots_list,_,_) ->
+ print_string arity;
+ print_string "\n("; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ (dots force_newline (statement arity))
+ statement_dots_list;
+ print_string "\n)"
+ | Ast0.Nest(starter,stmt_dots,ender,whn,multi) ->
+ print_string arity;
+ mcode print_string starter;
+ open_box 0;
+ List.iter
+ (whencode (dots force_newline (statement "")) (statement ""))
+ whn;
+ close_box();
+ start_block();
+ dots force_newline (statement arity) stmt_dots;
+ end_block();
+ mcode print_string ender
+ | Ast0.Exp(exp) -> print_string arity; expression exp
+ | Ast0.TopExp(exp) -> print_string arity; expression exp
+ | Ast0.Ty(ty) -> print_string arity; typeC ty
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
+ print_string arity; mcode print_string d;
+ List.iter
+ (whencode (dots force_newline (statement "")) (statement ""))
+ whn
+ | Ast0.Include(inc,s) ->
+ mcode print_string inc; print_string " "; mcode U.inc_file s
+ | Ast0.Define(def,id,params,body) ->
+ mcode print_string def; print_string " "; ident id;
+ print_define_parameters params;
+ print_string " ";
+ dots force_newline (statement arity) body
+ | Ast0.OptStm(re) -> statement "?" re
+ | Ast0.UniqueStm(re) -> statement "!" re)
+
+and print_define_parameters params =
+ match Ast0.unwrap params with
+ Ast0.NoParams -> ()
+ | Ast0.DParams(lp,params,rp) ->
+ mcode print_string lp;
+ dots (function _ -> ()) print_define_param params; mcode print_string rp
+
+and print_define_param param =
+ match Ast0.unwrap param with
+ Ast0.DParam(id) -> ident id
+ | Ast0.DPComma(comma) -> mcode print_string comma
+ | Ast0.DPdots(dots) -> mcode print_string dots
+ | Ast0.DPcircles(circles) -> mcode print_string circles
+ | Ast0.OptDParam(dp) -> print_string "?"; print_define_param dp
+ | Ast0.UniqueDParam(dp) -> print_string "!"; print_define_param dp
+
+and print_fninfo = function
+ Ast0.FStorage(stg) -> mcode U.storage stg
+ | Ast0.FType(ty) -> typeC ty
+ | Ast0.FInline(inline) -> mcode print_string inline
+ | Ast0.FAttr(attr) -> mcode print_string attr
+
+and whencode notfn alwaysfn = function
+ Ast0.WhenNot a ->
+ print_string " WHEN != "; open_box 0; notfn a; close_box()
+ | Ast0.WhenAlways a ->
+ print_string " WHEN = "; open_box 0; alwaysfn a; close_box()
+ | Ast0.WhenModifier x -> print_string " WHEN "; U.print_when_modif x
+
+and case_line arity c =
+ print_context c
+ (function _ ->
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ print_string arity;
+ mcode print_string def; mcode print_string colon; print_string " ";
+ dots force_newline (statement arity) code
+ | Ast0.Case(case,exp,colon,code) ->
+ print_string arity;
+ mcode print_string case; print_string " "; expression exp;
+ mcode print_string colon; print_string " ";
+ dots force_newline (statement arity) code
+ | Ast0.OptCase(case) -> case_line "?" case)
+
+and statement_dots l = dots (function _ -> ()) (statement "") l
+and case_dots l = dots (function _ -> ()) (case_line "") l
+
+(* --------------------------------------------------------------------- *)
+(* Top level code *)
+
+let top_level t =
+ print_context t
+ (function _ ->
+ match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ print_string "--- "; mcode print_string old_file; force_newline();
+ print_string "+++ "; mcode print_string new_file
+ | Ast0.DECL(stmt) -> statement "" stmt
+ | Ast0.CODE(stmt_dots) ->
+ dots force_newline (statement "") stmt_dots
+ | Ast0.ERRORWORDS(exps) ->
+ print_string "error words = [";
+ print_between (function _ -> print_string ", ") expression exps;
+ print_string "]"
+ | Ast0.OTHER(s) ->
+ print_string "OTHER("; statement "" s; print_string ")")
+
+let rule =
+ print_between (function _ -> force_newline(); force_newline()) top_level
+
+let unparse_anything x =
+ let q = !quiet in
+ quiet := true;
+ (match x with
+ Ast0.DotsExprTag(d) ->
+ print_string "ExpDots:"; force_newline();
+ expression_dots d
+ | Ast0.DotsParamTag(d) ->
+ parameter_list d
+ | Ast0.DotsInitTag(d) ->
+ initialiser_list d
+ | Ast0.DotsStmtTag(d) ->
+ print_string "StmDots:"; force_newline();
+ statement_dots d
+ | Ast0.DotsDeclTag(d) ->
+ declaration_dots d
+ | Ast0.DotsCaseTag(d) ->
+ case_dots d
+ | Ast0.IdentTag(d) ->
+ ident d
+ | Ast0.ExprTag(d) | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ print_string "Exp:"; force_newline();
+ expression d
+ | Ast0.TypeCTag(d) ->
+ typeC d
+ | Ast0.ParamTag(d) ->
+ parameterTypeDef d
+ | Ast0.InitTag(d) ->
+ initialiser d
+ | Ast0.DeclTag(d) ->
+ declaration d
+ | Ast0.StmtTag(d) ->
+ print_string "Stm:"; force_newline();
+ statement "" d
+ | Ast0.CaseLineTag(d) ->
+ case_line "" d
+ | Ast0.TopTag(d) ->
+ top_level d
+ | Ast0.IsoWhenTag(x) -> U.print_when_modif x
+ | Ast0.MetaPosTag(var) -> meta_pos var);
+ quiet := q;
+ print_newline()
+
+let unparse x =
+ print_string "\n@@\n@@";
+ force_newline();
+ force_newline();
+ rule x;
+ print_newline()
+
+let unparse_to_string x = Common.format_to_string (function _ -> unparse x)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+open Format
+module Ast0 = Ast0_cocci
+module U = Pretty_print_cocci
+
+let quiet = ref true (* true = no decoration on - context, etc *)
+
+let start_block str =
+ force_newline(); print_string " "; open_box 0
+
+let end_block str =
+ close_box(); force_newline ()
+
+let print_option = Common.do_option
+let print_between = Common.print_between
+
+(* --------------------------------------------------------------------- *)
+(* Positions *)
+
+let meta_pos = function
+ Ast0.MetaPos(name,_,_) ->
+ print_string "@";
+ let (_,name) = Ast0.unwrap_mcode name in
+ print_string name
+ | Ast0.NoMetaPos -> ()
+
+(* --------------------------------------------------------------------- *)
+(* Modified code *)
+
+let mcodekind brackets fn x info = function
+ Ast0.MINUS(plus_stream) ->
+ let (lb,rb) =
+ if !quiet
+ then ("","")
+ else
+ match brackets with
+ Some x -> ("[","]^"^(string_of_int x))
+ | None -> ("","") in
+ let (plus_stream,_) = !plus_stream in
+ if !quiet
+ then fn x
+ else (print_string "-";
+ print_string lb; fn x; print_string rb);
+ U.print_anything ">>> " plus_stream
+ | Ast0.CONTEXT(plus_streams) ->
+ let (lb,rb) =
+ if !quiet
+ then ("","")
+ else
+ match brackets with
+ Some x -> ("[",("]^"^(string_of_int x))) | None -> ("","") in
+ let (plus_streams,t1,t2) = !plus_streams in
+ U.print_around
+ (function x ->
+ print_string lb; fn x; print_string rb)
+ x plus_streams
+ | Ast0.PLUS ->
+ List.iter (function s -> print_string s; force_newline())
+ info.Ast0.strings_before;
+ fn x;
+ List.iter (function s -> force_newline(); print_string s)
+ info.Ast0.strings_after
+ | Ast0.MIXED(plus_streams) ->
+ let (lb,rb) =
+ if !quiet
+ then ("","")
+ else
+ let n =
+ match brackets with Some x -> "^"^(string_of_int x) | None -> "" in
+ ("§","½"^n) in
+ let (plus_streams,_,_) = !plus_streams in
+ U.print_around (function x -> print_string lb; fn x; print_string rb)
+ x plus_streams
+
+let mcode fn (x,_,info,mc,pos) =
+ let fn x = fn x; meta_pos !pos in
+ mcodekind (Some info.Ast0.line_start)(*None*) fn x info mc
+
+let print_context x fn =
+ mcodekind (Some (Ast0.get_line x)) fn () (Ast0.get_info x)
+ (Ast0.get_mcodekind x)
+
+let print_meta (_,name) = print_string name
+
+(* --------------------------------------------------------------------- *)
+(* --------------------------------------------------------------------- *)
+(* Dots *)
+
+let dots between fn d =
+ print_context d
+ (function _ ->
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) -> print_between between fn l
+ | Ast0.CIRCLES(l) -> print_between between fn l
+ | Ast0.STARS(l) -> print_between between fn l)
+
+(* --------------------------------------------------------------------- *)
+
+let print_types = function
+ None -> ()
+ | Some ty ->
+ print_string "/* ";
+ Format.print_flush();
+ print_between (function _ -> print_string ", ") Type_cocci.typeC ty;
+ Format.print_flush();
+ print_string " */"
+
+(* --------------------------------------------------------------------- *)
+(* Identifier *)
+
+let rec ident i =
+ print_context i
+ (function _ ->
+ match Ast0.unwrap i with
+ Ast0.Id(name) -> mcode print_string name
+ | Ast0.MetaId(name,_,_) -> mcode print_meta name
+ | Ast0.MetaFunc(name,_,_) -> mcode print_meta name
+ | Ast0.MetaLocalFunc(name,_,_) -> mcode print_meta name
+ | Ast0.OptIdent(id) -> print_string "?"; ident id
+ | Ast0.UniqueIdent(id) -> print_string "!"; ident id)
+
+(* --------------------------------------------------------------------- *)
+(* Expression *)
+
+let print_string_box s = print_string s; open_box 0
+
+let rec expression e =
+ print_option Type_cocci.typeC (Ast0.get_type e);
+ print_context e
+ (function _ ->
+ match Ast0.unwrap e with
+ Ast0.Ident(id) -> ident id
+ | Ast0.Constant(const) -> mcode U.constant const
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ expression fn; mcode print_string_box lp;
+ let _ = dots (function _ -> ()) expression args in
+ close_box(); mcode print_string rp
+ | Ast0.Assignment(left,op,right,_) ->
+ expression left; print_string " "; mcode U.assignOp op;
+ print_string " "; expression right
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ expression exp1; print_string " "; mcode print_string why;
+ print_option (function e -> print_string " "; expression e) exp2;
+ print_string " "; mcode print_string colon; expression exp3
+ | Ast0.Postfix(exp,op) -> expression exp; mcode U.fixOp op
+ | Ast0.Infix(exp,op) -> mcode U.fixOp op; expression exp
+ | Ast0.Unary(exp,op) -> mcode U.unaryOp op; expression exp
+ | Ast0.Binary(left,op,right) ->
+ print_string "(";
+ expression left; print_string " "; mcode U.binaryOp op;
+ print_string " "; expression right;
+ print_string ")"
+ | Ast0.Nested(left,op,right) ->
+ print_string "(";
+ expression left; print_string " "; mcode U.binaryOp op;
+ print_string " "; expression right;
+ print_string ")"
+ | Ast0.Paren(lp,exp,rp) ->
+ mcode print_string_box lp; expression exp; close_box();
+ mcode print_string rp
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ expression exp1; mcode print_string_box lb; expression exp2;
+ close_box(); mcode print_string rb
+ | Ast0.RecordAccess(exp,pt,field) ->
+ expression exp; mcode print_string pt; ident field
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ expression exp; mcode print_string ar; ident field
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ mcode print_string_box lp; typeC ty; close_box();
+ mcode print_string rp; expression exp
+ | Ast0.SizeOfExpr(szf,exp) ->
+ mcode print_string szf; expression exp
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ mcode print_string szf;
+ mcode print_string_box lp; typeC ty; close_box();
+ mcode print_string rp
+ | Ast0.TypeExp(ty) -> typeC ty
+ | Ast0.MetaErr(name,_,_) -> mcode print_meta name
+ | Ast0.MetaExpr(name,_,ty,_,_) ->
+ mcode print_meta name; print_types ty
+ | Ast0.MetaExprList(name,_,_) -> mcode print_meta name
+ | Ast0.EComma(cm) -> mcode print_string cm; print_space()
+ | Ast0.DisjExpr(_,exp_list,_,_) ->
+ print_string "\n("; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ expression exp_list;
+ print_string "\n)"
+ | Ast0.NestExpr(starter,expr_dots,ender,None,multi) ->
+ mcode print_string starter;
+ start_block(); dots force_newline expression expr_dots; end_block();
+ mcode print_string ender
+ | Ast0.NestExpr(starter,expr_dots,ender,Some whencode,multi) ->
+ mcode print_string starter; print_string " WHEN != ";
+ expression whencode;
+ start_block(); dots force_newline expression expr_dots; end_block();
+ mcode print_string ender
+ | Ast0.Edots(dots,Some whencode)
+ | Ast0.Ecircles(dots,Some whencode)
+ | Ast0.Estars(dots,Some whencode) ->
+ mcode print_string dots; print_string " WHEN != ";
+ expression whencode
+ | Ast0.Edots(dots,None)
+ | Ast0.Ecircles(dots,None)
+ | Ast0.Estars(dots,None) -> mcode print_string dots
+ | Ast0.OptExp(exp) -> print_string "?"; expression exp
+ | Ast0.UniqueExp(exp) -> print_string "!"; expression exp)
+
+and expression_dots x = dots (function _ -> ()) expression x
+
+(* --------------------------------------------------------------------- *)
+(* Types *)
+
+and print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2) fn =
+ typeC ty; mcode print_string lp1; mcode print_string star; fn();
+ mcode print_string rp1; mcode print_string lp2;
+ parameter_list params; mcode print_string rp2
+
+and print_function_type (ty,lp1,params,rp1) fn =
+ print_option typeC ty; fn(); mcode print_string lp1;
+ parameter_list params; mcode print_string rp1
+
+and typeC t =
+ print_context t
+ (function _ ->
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) ->
+ mcode U.const_vol cv; print_string " "; typeC ty
+ | Ast0.BaseType(ty,sgn) ->
+ print_option (mcode U.sign) sgn; mcode U.baseType ty
+ | Ast0.ImplicitInt(sgn) -> mcode U.sign sgn
+ | Ast0.Pointer(ty,star) -> typeC ty; mcode print_string star
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> ())
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1) (function _ -> ())
+ | Ast0.Array(ty,lb,size,rb) ->
+ typeC ty; mcode print_string lb; print_option expression size;
+ mcode print_string rb
+ | Ast0.StructUnionName(kind,name) ->
+ mcode U.structUnion kind;
+ print_option (function x -> ident x; print_string " ") name
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ typeC ty; mcode print_string lb;
+ dots force_newline declaration decls;
+ mcode print_string rb
+ | Ast0.TypeName(name)-> mcode print_string name; print_string " "
+ | Ast0.MetaType(name,_)-> mcode print_meta name; print_string " "
+ | Ast0.DisjType(lp,types,mids,rp) ->
+ print_string "\n"; mcode print_string lp; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ typeC types;
+ print_string "\n"; mcode print_string rp
+ | Ast0.OptType(ty) -> print_string "?"; typeC ty
+ | Ast0.UniqueType(ty) -> print_string "!"; typeC ty)
+
+(* --------------------------------------------------------------------- *)
+(* Variable declaration *)
+(* Even if the Cocci program specifies a list of declarations, they are
+ split out into multiple declarations of a single variable each. *)
+
+and print_named_type ty id =
+ match Ast0.unwrap ty with
+ Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ print_function_pointer (ty,lp1,star,rp1,lp2,params,rp2)
+ (function _ -> print_string " "; ident id)
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ print_function_type (ty,lp1,params,rp1)
+ (function _ -> print_string " "; ident id)
+ | Ast0.Array(ty,lb,size,rb) ->
+ let rec loop ty k =
+ match Ast0.unwrap ty with
+ Ast0.Array(ty,lb,size,rb) ->
+ loop ty
+ (function _ ->
+ k ();
+ mcode print_string lb;
+ print_option expression size;
+ mcode print_string rb)
+ | _ -> typeC ty; ident id; k () in
+ loop ty (function _ -> ())
+ | _ -> typeC ty; ident id
+
+and declaration d =
+ print_context d
+ (function _ ->
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ print_option (mcode U.storage) stg;
+ print_named_type ty id;
+ print_string " ";
+ mcode print_string eq; print_string " "; initialiser ini;
+ mcode print_string sem
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ print_option (mcode U.storage) stg; print_named_type ty id;
+ mcode print_string sem
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ ident name; mcode print_string_box lp;
+ let _ = dots (function _ -> ()) expression args in
+ close_box(); mcode print_string rp; mcode print_string sem
+ | Ast0.TyDecl(ty,sem) -> typeC ty; mcode print_string sem
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ mcode print_string stg; typeC ty; typeC id;
+ mcode print_string sem
+ | Ast0.DisjDecl(_,decls,_,_) ->
+ print_string "\n("; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ declaration decls;
+ print_string "\n)"
+ | Ast0.Ddots(dots,Some whencode) ->
+ mcode print_string dots; print_string " when != ";
+ declaration whencode
+ | Ast0.Ddots(dots,None) -> mcode print_string dots
+ | Ast0.OptDecl(decl) -> print_string "?"; declaration decl
+ | Ast0.UniqueDecl(decl) -> print_string "!"; declaration decl)
+
+and declaration_dots l = dots (function _ -> ()) declaration l
+
+(* --------------------------------------------------------------------- *)
+(* Initialiser *)
+
+and initialiser i =
+ print_context i
+ (function _ ->
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> expression exp
+ | Ast0.InitList(lb,initlist,rb) ->
+ mcode print_string lb; open_box 0;
+ let _ = dots (function _ -> ()) initialiser initlist in
+ close_box(); mcode print_string rb
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ mcode print_string dot; ident name; print_string " ";
+ mcode print_string eq; print_string " "; initialiser ini
+ | Ast0.InitGccName(name,eq,ini) ->
+ ident name; mcode print_string eq; initialiser ini
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ mcode print_string lb; expression exp; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ mcode print_string lb; expression exp1; mcode print_string dots;
+ expression exp2; mcode print_string rb;
+ print_string " "; mcode print_string eq; print_string " ";
+ initialiser ini
+ | Ast0.IComma(cm) -> mcode print_string cm; force_newline()
+ | Ast0.Idots(d,Some whencode) ->
+ mcode print_string d; print_string " WHEN != ";
+ initialiser whencode
+ | Ast0.Idots(d,None) -> mcode print_string d
+ | Ast0.OptIni(ini) -> print_string "?"; initialiser ini
+ | Ast0.UniqueIni(ini) -> print_string "!"; initialiser ini)
+
+and initialiser_list l = dots (function _ -> ()) initialiser l
+
+(* --------------------------------------------------------------------- *)
+(* Parameter *)
+
+and parameterTypeDef p =
+ print_context p
+ (function _ ->
+ match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> typeC ty
+ | Ast0.Param(ty,Some id) -> print_named_type ty id
+ | Ast0.Param(ty,None) -> typeC ty
+ | Ast0.MetaParam(name,_) -> mcode print_meta name
+ | Ast0.MetaParamList(name,_,_) -> mcode print_meta name
+ | Ast0.PComma(cm) -> mcode print_string cm; print_space()
+ | Ast0.Pdots(dots) -> mcode print_string dots
+ | Ast0.Pcircles(dots) -> mcode print_string dots
+ | Ast0.OptParam(param) -> print_string "?"; parameterTypeDef param
+ | Ast0.UniqueParam(param) -> print_string "!"; parameterTypeDef param)
+
+and parameter_list l = dots (function _ -> ()) parameterTypeDef l
+
+(* --------------------------------------------------------------------- *)
+(* Top-level code *)
+
+and statement arity s =
+ print_context s
+ (function _ ->
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
+ print_string arity;
+ List.iter print_fninfo fninfo;
+ ident name; mcode print_string_box lp;
+ parameter_list params; close_box(); mcode print_string rp;
+ print_string " ";
+ print_string arity; mcode print_string lbrace; start_block();
+ dots force_newline (statement arity) body;
+ end_block(); print_string arity; mcode print_string rbrace
+ | Ast0.Decl(_,decl) -> print_string arity; declaration decl
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ print_string arity; mcode print_string lbrace; start_block();
+ dots force_newline (statement arity) body;
+ end_block(); print_string arity; mcode print_string rbrace
+ | Ast0.ExprStatement(exp,sem) ->
+ print_string arity; expression exp; mcode print_string sem
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,(info,aft)) ->
+ print_string arity;
+ mcode print_string iff; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " ";
+ statement arity branch1;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,aft)) ->
+ print_string arity;
+ mcode print_string iff; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " ";
+ statement arity branch1;
+ print_string arity; mcode print_string els; print_string " ";
+ statement arity branch2;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.While(whl,lp,exp,rp,body,(info,aft)) ->
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp; print_string " ";
+ statement arity body;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
+ print_string arity; mcode print_string d; print_string " ";
+ statement arity body;
+ print_string arity;
+ mcode print_string whl; print_string " "; mcode print_string_box lp;
+ expression exp; close_box(); mcode print_string rp;
+ mcode print_string sem
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,(info,aft)) ->
+ print_string arity;
+ mcode print_string fr; mcode print_string_box lp;
+ print_option expression e1; mcode print_string sem1;
+ print_option expression e2; mcode print_string sem2;
+ print_option expression e3; close_box();
+ mcode print_string rp; print_string " "; statement arity body;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.Iterator(nm,lp,args,rp,body,(info,aft)) ->
+ print_string arity;
+ ident nm; print_string " "; mcode print_string_box lp;
+ let _ = dots (function _ -> ()) expression args in
+ close_box(); mcode print_string rp; print_string " ";
+ statement arity body;
+ mcode (function _ -> ()) ((),(),info,aft,ref Ast0.NoMetaPos)
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ print_string arity;
+ mcode print_string switch; print_string " ";
+ mcode print_string_box lp; expression exp; close_box();
+ mcode print_string rp; print_string " "; mcode print_string lb;
+ dots force_newline (case_line arity) cases;
+ mcode print_string rb
+ | Ast0.Break(br,sem) ->
+ print_string arity; mcode print_string br; mcode print_string sem
+ | Ast0.Continue(cont,sem) ->
+ print_string arity; mcode print_string cont; mcode print_string sem
+ | Ast0.Label(l,dd) -> ident l; print_string ":"
+ | Ast0.Goto(goto,l,sem) ->
+ mcode print_string goto; ident l; mcode print_string sem
+ | Ast0.Return(ret,sem) ->
+ print_string arity; mcode print_string ret; mcode print_string sem
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ print_string arity; mcode print_string ret; print_string " ";
+ expression exp; mcode print_string sem
+ | Ast0.MetaStmt(name,pure) ->
+ print_string arity; mcode print_meta name;(*
+ print_string "^";
+ (match pure with
+ Ast0.Pure -> print_string "pure"
+ | Ast0.Impure -> print_string "impure"
+ | Ast0.Context -> print_string "context"
+ | Ast0.PureContext -> print_string "pure_context")*)
+ | Ast0.MetaStmtList(name,_) ->
+ print_string arity; mcode print_meta name
+ | Ast0.Disj(_,statement_dots_list,_,_) ->
+ print_string arity;
+ print_string "\n("; force_newline();
+ print_between
+ (function _ -> print_string "\n|"; force_newline())
+ (dots force_newline (statement arity))
+ statement_dots_list;
+ print_string "\n)"
+ | Ast0.Nest(starter,stmt_dots,ender,whn,multi) ->
+ print_string arity;
+ mcode print_string starter;
+ open_box 0;
+ List.iter
+ (whencode (dots force_newline (statement "")) (statement ""))
+ whn;
+ close_box();
+ start_block();
+ dots force_newline (statement arity) stmt_dots;
+ end_block();
+ mcode print_string ender
+ | Ast0.Exp(exp) -> print_string arity; expression exp
+ | Ast0.TopExp(exp) -> print_string arity; expression exp
+ | Ast0.Ty(ty) -> print_string arity; typeC ty
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
+ print_string arity; mcode print_string d;
+ List.iter
+ (whencode (dots force_newline (statement "")) (statement ""))
+ whn
+ | Ast0.Include(inc,s) ->
+ mcode print_string inc; print_string " "; mcode U.inc_file s
+ | Ast0.Define(def,id,params,body) ->
+ mcode print_string def; print_string " "; ident id;
+ print_define_parameters params;
+ print_string " ";
+ dots force_newline (statement arity) body
+ | Ast0.OptStm(re) -> statement "?" re
+ | Ast0.UniqueStm(re) -> statement "!" re)
+
+and print_define_parameters params =
+ match Ast0.unwrap params with
+ Ast0.NoParams -> ()
+ | Ast0.DParams(lp,params,rp) ->
+ mcode print_string lp;
+ dots (function _ -> ()) print_define_param params; mcode print_string rp
+
+and print_define_param param =
+ match Ast0.unwrap param with
+ Ast0.DParam(id) -> ident id
+ | Ast0.DPComma(comma) -> mcode print_string comma
+ | Ast0.DPdots(dots) -> mcode print_string dots
+ | Ast0.DPcircles(circles) -> mcode print_string circles
+ | Ast0.OptDParam(dp) -> print_string "?"; print_define_param dp
+ | Ast0.UniqueDParam(dp) -> print_string "!"; print_define_param dp
+
+and print_fninfo = function
+ Ast0.FStorage(stg) -> mcode U.storage stg
+ | Ast0.FType(ty) -> typeC ty
+ | Ast0.FInline(inline) -> mcode print_string inline
+ | Ast0.FAttr(attr) -> mcode print_string attr
+
+and whencode notfn alwaysfn = function
+ Ast0.WhenNot a ->
+ print_string " WHEN != "; open_box 0; notfn a; close_box()
+ | Ast0.WhenAlways a ->
+ print_string " WHEN = "; open_box 0; alwaysfn a; close_box()
+ | Ast0.WhenModifier x -> print_string " WHEN "; U.print_when_modif x
+ | Ast0.WhenNotTrue a ->
+ print_string " WHEN != TRUE "; open_box 0; expression a; close_box()
+ | Ast0.WhenNotFalse a ->
+ print_string " WHEN != FALSE "; open_box 0; expression a; close_box()
+
+and case_line arity c =
+ print_context c
+ (function _ ->
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ print_string arity;
+ mcode print_string def; mcode print_string colon; print_string " ";
+ dots force_newline (statement arity) code
+ | Ast0.Case(case,exp,colon,code) ->
+ print_string arity;
+ mcode print_string case; print_string " "; expression exp;
+ mcode print_string colon; print_string " ";
+ dots force_newline (statement arity) code
+ | Ast0.OptCase(case) -> case_line "?" case)
+
+and statement_dots l = dots (function _ -> ()) (statement "") l
+and case_dots l = dots (function _ -> ()) (case_line "") l
+
+(* --------------------------------------------------------------------- *)
+(* Top level code *)
+
+let top_level t =
+ print_context t
+ (function _ ->
+ match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ print_string "--- "; mcode print_string old_file; force_newline();
+ print_string "+++ "; mcode print_string new_file
+ | Ast0.DECL(stmt) -> statement "" stmt
+ | Ast0.CODE(stmt_dots) ->
+ dots force_newline (statement "") stmt_dots
+ | Ast0.ERRORWORDS(exps) ->
+ print_string "error words = [";
+ print_between (function _ -> print_string ", ") expression exps;
+ print_string "]"
+ | Ast0.OTHER(s) ->
+ print_string "OTHER("; statement "" s; print_string ")")
+
+let rule =
+ print_between (function _ -> force_newline(); force_newline()) top_level
+
+let unparse_anything x =
+ let q = !quiet in
+ quiet := true;
+ (match x with
+ Ast0.DotsExprTag(d) ->
+ print_string "ExpDots:"; force_newline();
+ expression_dots d
+ | Ast0.DotsParamTag(d) ->
+ parameter_list d
+ | Ast0.DotsInitTag(d) ->
+ initialiser_list d
+ | Ast0.DotsStmtTag(d) ->
+ print_string "StmDots:"; force_newline();
+ statement_dots d
+ | Ast0.DotsDeclTag(d) ->
+ declaration_dots d
+ | Ast0.DotsCaseTag(d) ->
+ case_dots d
+ | Ast0.IdentTag(d) ->
+ ident d
+ | Ast0.ExprTag(d) | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
+ print_string "Exp:"; force_newline();
+ expression d
+ | Ast0.TypeCTag(d) ->
+ typeC d
+ | Ast0.ParamTag(d) ->
+ parameterTypeDef d
+ | Ast0.InitTag(d) ->
+ initialiser d
+ | Ast0.DeclTag(d) ->
+ declaration d
+ | Ast0.StmtTag(d) ->
+ print_string "Stm:"; force_newline();
+ statement "" d
+ | Ast0.CaseLineTag(d) ->
+ case_line "" d
+ | Ast0.TopTag(d) ->
+ top_level d
+ | Ast0.IsoWhenTag(x) -> U.print_when_modif x
+ | Ast0.IsoWhenTTag(e) -> expression e
+ | Ast0.IsoWhenFTag(e) -> expression e
+ | Ast0.MetaPosTag(var) -> meta_pos var);
+ quiet := q;
+ print_newline()
+
+let unparse x =
+ print_string "\n@@\n@@";
+ force_newline();
+ force_newline();
+ rule x;
+ print_newline()
+
+let unparse_to_string x = Common.format_to_string (function _ -> unparse x)
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+
+(* --------------------------------------------------------------------- *)
+(* Generic traversal: combiner *)
+(* parameters:
+ combining function
+ treatment of: mcode, identifiers, expressions, fullTypes, types,
+ declarations, statements, toplevels
+ default value for options *)
+
+type 'a combiner =
+ {combiner_ident : Ast.ident -> 'a;
+ combiner_expression : Ast.expression -> 'a;
+ combiner_fullType : Ast.fullType -> 'a;
+ combiner_typeC : Ast.typeC -> 'a;
+ combiner_declaration : Ast.declaration -> 'a;
+ combiner_initialiser : Ast.initialiser -> 'a;
+ combiner_parameter : Ast.parameterTypeDef -> 'a;
+ combiner_parameter_list : Ast.parameter_list -> 'a;
+ combiner_rule_elem : Ast.rule_elem -> 'a;
+ combiner_statement : Ast.statement -> 'a;
+ combiner_case_line : Ast.case_line -> 'a;
+ combiner_top_level : Ast.top_level -> 'a;
+ combiner_anything : Ast.anything -> 'a;
+ combiner_expression_dots : Ast.expression Ast.dots -> 'a;
+ combiner_statement_dots : Ast.statement Ast.dots -> 'a;
+ combiner_declaration_dots : Ast.declaration Ast.dots -> 'a}
+
+type ('mc,'a) cmcode = 'a combiner -> 'mc Ast_cocci.mcode -> 'a
+type ('cd,'a) ccode = 'a combiner -> ('cd -> 'a) -> 'cd -> 'a
+
+
+let combiner bind option_default
+ meta_mcodefn string_mcodefn const_mcodefn assign_mcodefn fix_mcodefn
+ unary_mcodefn binary_mcodefn
+ cv_mcodefn base_mcodefn sign_mcodefn struct_mcodefn storage_mcodefn
+ inc_file_mcodefn
+ expdotsfn paramdotsfn stmtdotsfn decldotsfn
+ identfn exprfn ftfn tyfn initfn paramfn declfn rulefn stmtfn casefn
+ topfn anyfn =
+ let multibind l =
+ let rec loop = function
+ [] -> option_default
+ | [x] -> x
+ | x::xs -> bind x (loop xs) in
+ loop l in
+ let get_option f = function
+ Some x -> f x
+ | None -> option_default in
+
+ let rec meta_mcode x = meta_mcodefn all_functions x
+ and string_mcode x = string_mcodefn all_functions x
+ and const_mcode x = const_mcodefn all_functions x
+ and assign_mcode x = assign_mcodefn all_functions x
+ and fix_mcode x = fix_mcodefn all_functions x
+ and unary_mcode x = unary_mcodefn all_functions x
+ and binary_mcode x = binary_mcodefn all_functions x
+ and cv_mcode x = cv_mcodefn all_functions x
+ and base_mcode x = base_mcodefn all_functions x
+ and sign_mcode x = sign_mcodefn all_functions x
+ and struct_mcode x = struct_mcodefn all_functions x
+ and storage_mcode x = storage_mcodefn all_functions x
+ and inc_file_mcode x = inc_file_mcodefn all_functions x
+
+ and expression_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map expression l) in
+ expdotsfn all_functions k d
+
+ and parameter_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map parameterTypeDef l) in
+ paramdotsfn all_functions k d
+
+ and statement_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map statement l) in
+ stmtdotsfn all_functions k d
+
+ and declaration_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map declaration l) in
+ decldotsfn all_functions k d
+
+ and ident i =
+ let k i =
+ match Ast.unwrap i with
+ Ast.Id(name) -> string_mcode name
+ | Ast.MetaId(name,_,_,_) -> meta_mcode name
+ | Ast.MetaFunc(name,_,_,_) -> meta_mcode name
+ | Ast.MetaLocalFunc(name,_,_,_) -> meta_mcode name
+ | Ast.OptIdent(id) -> ident id
+ | Ast.UniqueIdent(id) -> ident id in
+ identfn all_functions k i
+
+ and expression e =
+ let k e =
+ match Ast.unwrap e with
+ Ast.Ident(id) -> ident id
+ | Ast.Constant(const) -> const_mcode const
+ | Ast.FunCall(fn,lp,args,rp) ->
+ multibind [expression fn; string_mcode lp; expression_dots args;
+ string_mcode rp]
+ | Ast.Assignment(left,op,right,simple) ->
+ multibind [expression left; assign_mcode op; expression right]
+ | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
+ multibind [expression exp1; string_mcode why;
+ get_option expression exp2; string_mcode colon;
+ expression exp3]
+ | Ast.Postfix(exp,op) -> bind (expression exp) (fix_mcode op)
+ | Ast.Infix(exp,op) -> bind (fix_mcode op) (expression exp)
+ | Ast.Unary(exp,op) -> bind (unary_mcode op) (expression exp)
+ | Ast.Binary(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast.Nested(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast.Paren(lp,exp,rp) ->
+ multibind [string_mcode lp; expression exp; string_mcode rp]
+ | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
+ multibind
+ [expression exp1; string_mcode lb; expression exp2;
+ string_mcode rb]
+ | Ast.RecordAccess(exp,pt,field) ->
+ multibind [expression exp; string_mcode pt; ident field]
+ | Ast.RecordPtAccess(exp,ar,field) ->
+ multibind [expression exp; string_mcode ar; ident field]
+ | Ast.Cast(lp,ty,rp,exp) ->
+ multibind
+ [string_mcode lp; fullType ty; string_mcode rp; expression exp]
+ | Ast.SizeOfExpr(szf,exp) ->
+ multibind [string_mcode szf; expression exp]
+ | Ast.SizeOfType(szf,lp,ty,rp) ->
+ multibind
+ [string_mcode szf; string_mcode lp; fullType ty; string_mcode rp]
+ | Ast.TypeExp(ty) -> fullType ty
+ | Ast.MetaErr(name,_,_,_)
+ | Ast.MetaExpr(name,_,_,_,_,_)
+ | Ast.MetaExprList(name,_,_,_) -> meta_mcode name
+ | Ast.EComma(cm) -> string_mcode cm
+ | Ast.DisjExpr(exp_list) -> multibind (List.map expression exp_list)
+ | Ast.NestExpr(expr_dots,whencode,multi) ->
+ bind (expression_dots expr_dots) (get_option expression whencode)
+ | Ast.Edots(dots,whencode) | Ast.Ecircles(dots,whencode)
+ | Ast.Estars(dots,whencode) ->
+ bind (string_mcode dots) (get_option expression whencode)
+ | Ast.OptExp(exp) | Ast.UniqueExp(exp) ->
+ expression exp in
+ exprfn all_functions k e
+
+ and fullType ft =
+ let k ft =
+ match Ast.unwrap ft with
+ Ast.Type(cv,ty) -> bind (get_option cv_mcode cv) (typeC ty)
+ | Ast.DisjType(types) -> multibind (List.map fullType types)
+ | Ast.OptType(ty) -> fullType ty
+ | Ast.UniqueType(ty) -> fullType ty in
+ ftfn all_functions k ft
+
+ and function_pointer (ty,lp1,star,rp1,lp2,params,rp2) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind
+ ([fullType ty; string_mcode lp1; string_mcode star] @ extra @
+ [string_mcode rp1;
+ string_mcode lp2; parameter_dots params; string_mcode rp2])
+
+ and function_type (ty,lp1,params,rp1) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind
+ ([get_option fullType ty] @ extra @
+ [string_mcode lp1; parameter_dots params; string_mcode rp1])
+
+ and array_type (ty,lb,size,rb) extra =
+ multibind
+ ([fullType ty] @ extra @
+ [string_mcode lb; get_option expression size; string_mcode rb])
+
+ and typeC ty =
+ let k ty =
+ match Ast.unwrap ty with
+ Ast.BaseType(ty,sgn) ->
+ bind (get_option sign_mcode sgn) (base_mcode ty)
+ | Ast.ImplicitInt(sgn) -> sign_mcode sgn
+ | Ast.Pointer(ty,star) ->
+ bind (fullType ty) (string_mcode star)
+ | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) []
+ | Ast.FunctionType (_,ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) []
+ | Ast.Array(ty,lb,size,rb) -> array_type (ty,lb,size,rb) []
+ | Ast.StructUnionName(kind,name) ->
+ bind (struct_mcode kind) (get_option ident name)
+ | Ast.StructUnionDef(ty,lb,decls,rb) ->
+ multibind
+ [fullType ty; string_mcode lb; declaration_dots decls;
+ string_mcode rb]
+ | Ast.TypeName(name) -> string_mcode name
+ | Ast.MetaType(name,_,_) -> meta_mcode name in
+ tyfn all_functions k ty
+
+ and named_type ty id =
+ match Ast.unwrap ty with
+ Ast.Type(None,ty1) ->
+ (match Ast.unwrap ty1 with
+ Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) [ident id]
+ | Ast.FunctionType(_,ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) [ident id]
+ | Ast.Array(ty,lb,size,rb) -> array_type (ty,lb,size,rb) [ident id]
+ | _ -> bind (fullType ty) (ident id))
+ | _ -> bind (fullType ty) (ident id)
+
+ and declaration d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.Init(stg,ty,id,eq,ini,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id)
+ (multibind
+ [string_mcode eq; initialiser ini; string_mcode sem]))
+ | Ast.UnInit(stg,ty,id,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id) (string_mcode sem))
+ | Ast.MacroDecl(name,lp,args,rp,sem) ->
+ multibind
+ [ident name; string_mcode lp; expression_dots args;
+ string_mcode rp; string_mcode sem]
+ | Ast.TyDecl(ty,sem) -> bind (fullType ty) (string_mcode sem)
+ | Ast.Typedef(stg,ty,id,sem) ->
+ bind (string_mcode stg)
+ (bind (fullType ty) (bind (typeC id) (string_mcode sem)))
+ | Ast.DisjDecl(decls) -> multibind (List.map declaration decls)
+ | Ast.Ddots(dots,whencode) ->
+ bind (string_mcode dots) (get_option declaration whencode)
+ | Ast.MetaDecl(name,_,_) -> meta_mcode name
+ | Ast.OptDecl(decl) -> declaration decl
+ | Ast.UniqueDecl(decl) -> declaration decl in
+ declfn all_functions k d
+
+ and initialiser i =
+ let k i =
+ match Ast.unwrap i with
+ Ast.InitExpr(exp) -> expression exp
+ | Ast.InitList(lb,initlist,rb,whencode) ->
+ multibind
+ [string_mcode lb;
+ multibind (List.map initialiser initlist);
+ string_mcode rb;
+ multibind (List.map initialiser whencode)]
+ | Ast.InitGccDotName(dot,name,eq,ini) ->
+ multibind
+ [string_mcode dot; ident name; string_mcode eq; initialiser ini]
+ | Ast.InitGccName(name,eq,ini) ->
+ multibind [ident name; string_mcode eq; initialiser ini]
+ | Ast.InitGccIndex(lb,exp,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp; string_mcode rb;
+ string_mcode eq; initialiser ini]
+ | Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp1; string_mcode dots;
+ expression exp2; string_mcode rb; string_mcode eq;
+ initialiser ini]
+ | Ast.IComma(cm) -> string_mcode cm
+ | Ast.OptIni(i) -> initialiser i
+ | Ast.UniqueIni(i) -> initialiser i in
+ initfn all_functions k i
+
+ and parameterTypeDef p =
+ let k p =
+ match Ast.unwrap p with
+ Ast.VoidParam(ty) -> fullType ty
+ | Ast.Param(ty,Some id) -> named_type ty id
+ | Ast.Param(ty,None) -> fullType ty
+ | Ast.MetaParam(name,_,_) -> meta_mcode name
+ | Ast.MetaParamList(name,_,_,_) -> meta_mcode name
+ | Ast.PComma(cm) -> string_mcode cm
+ | Ast.Pdots(dots) -> string_mcode dots
+ | Ast.Pcircles(dots) -> string_mcode dots
+ | Ast.OptParam(param) -> parameterTypeDef param
+ | Ast.UniqueParam(param) -> parameterTypeDef param in
+ paramfn all_functions k p
+
+ and rule_elem re =
+ let k re =
+ match Ast.unwrap re with
+ Ast.FunHeader(_,_,fi,name,lp,params,rp) ->
+ multibind
+ ((List.map fninfo fi) @
+ [ident name;string_mcode lp;parameter_dots params;
+ string_mcode rp])
+ | Ast.Decl(_,_,decl) -> declaration decl
+ | Ast.SeqStart(brace) -> string_mcode brace
+ | Ast.SeqEnd(brace) -> string_mcode brace
+ | Ast.ExprStatement(exp,sem) ->
+ bind (expression exp) (string_mcode sem)
+ | Ast.IfHeader(iff,lp,exp,rp) ->
+ multibind [string_mcode iff; string_mcode lp; expression exp;
+ string_mcode rp]
+ | Ast.Else(els) -> string_mcode els
+ | Ast.WhileHeader(whl,lp,exp,rp) ->
+ multibind [string_mcode whl; string_mcode lp; expression exp;
+ string_mcode rp]
+ | Ast.DoHeader(d) -> string_mcode d
+ | Ast.WhileTail(whl,lp,exp,rp,sem) ->
+ multibind [string_mcode whl; string_mcode lp; expression exp;
+ string_mcode rp; string_mcode sem]
+ | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
+ multibind [string_mcode fr; string_mcode lp;
+ get_option expression e1; string_mcode sem1;
+ get_option expression e2; string_mcode sem2;
+ get_option expression e3; string_mcode rp]
+ | Ast.IteratorHeader(nm,lp,args,rp) ->
+ multibind [ident nm; string_mcode lp;
+ expression_dots args; string_mcode rp]
+ | Ast.SwitchHeader(switch,lp,exp,rp) ->
+ multibind [string_mcode switch; string_mcode lp; expression exp;
+ string_mcode rp]
+ | Ast.Break(br,sem) -> bind (string_mcode br) (string_mcode sem)
+ | Ast.Continue(cont,sem) -> bind (string_mcode cont) (string_mcode sem)
+ | Ast.Label(l,dd) -> bind (ident l) (string_mcode dd)
+ | Ast.Goto(goto,l,sem) ->
+ bind (string_mcode goto) (bind (ident l) (string_mcode sem))
+ | Ast.Return(ret,sem) -> bind (string_mcode ret) (string_mcode sem)
+ | Ast.ReturnExpr(ret,exp,sem) ->
+ multibind [string_mcode ret; expression exp; string_mcode sem]
+ | Ast.MetaStmt(name,_,_,_) -> meta_mcode name
+ | Ast.MetaStmtList(name,_,_) -> meta_mcode name
+ | Ast.MetaRuleElem(name,_,_) -> meta_mcode name
+ | Ast.Exp(exp) -> expression exp
+ | Ast.TopExp(exp) -> expression exp
+ | Ast.Ty(ty) -> fullType ty
+ | Ast.Include(inc,name) -> bind (string_mcode inc) (inc_file_mcode name)
+ | Ast.DefineHeader(def,id,params) ->
+ multibind [string_mcode def; ident id; define_parameters params]
+ | Ast.Default(def,colon) -> bind (string_mcode def) (string_mcode colon)
+ | Ast.Case(case,exp,colon) ->
+ multibind [string_mcode case; expression exp; string_mcode colon]
+ | Ast.DisjRuleElem(res) -> multibind (List.map rule_elem res) in
+ rulefn all_functions k re
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ match Ast.unwrap p with
+ Ast.NoParams -> option_default
+ | Ast.DParams(lp,params,rp) ->
+ multibind
+ [string_mcode lp; define_param_dots params; string_mcode rp] in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map define_param l) in
+ k d
+
+ and define_param p =
+ let k p =
+ match Ast.unwrap p with
+ Ast.DParam(id) -> ident id
+ | Ast.DPComma(comma) -> string_mcode comma
+ | Ast.DPdots(d) -> string_mcode d
+ | Ast.DPcircles(c) -> string_mcode c
+ | Ast.OptDParam(dp) -> define_param dp
+ | Ast.UniqueDParam(dp) -> define_param dp in
+ k p
+
+ (* discard the result, because the statement is assumed to be already
+ represented elsewhere in the code *)
+ and process_bef_aft s =
+ match Ast.get_dots_bef_aft s with
+ Ast.NoDots -> ()
+ | Ast.DroppingBetweenDots(stm,ind) -> let _ = statement stm in ()
+ | Ast.AddingBetweenDots(stm,ind) -> let _ = statement stm in ()
+
+ and statement s =
+ process_bef_aft s;
+ let k s =
+ match Ast.unwrap s with
+ Ast.Seq(lbrace,decls,body,rbrace) ->
+ multibind [rule_elem lbrace; statement_dots decls;
+ statement_dots body; rule_elem rbrace]
+ | Ast.IfThen(header,branch,_) ->
+ multibind [rule_elem header; statement branch]
+ | Ast.IfThenElse(header,branch1,els,branch2,_) ->
+ multibind [rule_elem header; statement branch1; rule_elem els;
+ statement branch2]
+ | Ast.While(header,body,_) ->
+ multibind [rule_elem header; statement body]
+ | Ast.Do(header,body,tail) ->
+ multibind [rule_elem header; statement body; rule_elem tail]
+ | Ast.For(header,body,_) -> multibind [rule_elem header; statement body]
+ | Ast.Iterator(header,body,_) ->
+ multibind [rule_elem header; statement body]
+ | Ast.Switch(header,lb,cases,rb) ->
+ multibind [rule_elem header;rule_elem lb;
+ multibind (List.map case_line cases);
+ rule_elem rb]
+ | Ast.Atomic(re) -> rule_elem re
+ | Ast.Disj(stmt_dots_list) ->
+ multibind (List.map statement_dots stmt_dots_list)
+ | Ast.Nest(stmt_dots,whn,_,_,_) ->
+ bind (statement_dots stmt_dots)
+ (multibind (List.map (whencode statement_dots statement) whn))
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ multibind [rule_elem header; rule_elem lbrace;
+ statement_dots decls; statement_dots body;
+ rule_elem rbrace]
+ | Ast.Define(header,body) ->
+ bind (rule_elem header) (statement_dots body)
+ | Ast.Dots(d,whn,_,_) | Ast.Circles(d,whn,_,_) | Ast.Stars(d,whn,_,_) ->
+ bind (string_mcode d)
+ (multibind (List.map (whencode statement_dots statement) whn))
+ | Ast.OptStm(stmt) | Ast.UniqueStm(stmt) ->
+ statement stmt in
+ stmtfn all_functions k s
+
+ and fninfo = function
+ Ast.FStorage(stg) -> storage_mcode stg
+ | Ast.FType(ty) -> fullType ty
+ | Ast.FInline(inline) -> string_mcode inline
+ | Ast.FAttr(attr) -> string_mcode attr
+
+ and whencode notfn alwaysfn = function
+ Ast.WhenNot a -> notfn a
+ | Ast.WhenAlways a -> alwaysfn a
+ | Ast.WhenModifier(_) -> option_default
+
+ and case_line c =
+ let k c =
+ match Ast.unwrap c with
+ Ast.CaseLine(header,code) ->
+ bind (rule_elem header) (statement_dots code)
+ | Ast.OptCase(case) -> case_line case in
+ casefn all_functions k c
+
+ and top_level t =
+ let k t =
+ match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) ->
+ bind (string_mcode old_file) (string_mcode new_file)
+ | Ast.DECL(stmt) -> statement stmt
+ | Ast.CODE(stmt_dots) -> statement_dots stmt_dots
+ | Ast.ERRORWORDS(exps) -> multibind (List.map expression exps) in
+ topfn all_functions k t
+
+ and anything a =
+ let k = function
+ (*in many cases below, the thing is not even mcode, so we do nothing*)
+ Ast.FullTypeTag(ft) -> fullType ft
+ | Ast.BaseTypeTag(bt) -> option_default
+ | Ast.StructUnionTag(su) -> option_default
+ | Ast.SignTag(sgn) -> option_default
+ | Ast.IdentTag(id) -> ident id
+ | Ast.ExpressionTag(exp) -> expression exp
+ | Ast.ConstantTag(cst) -> option_default
+ | Ast.UnaryOpTag(unop) -> option_default
+ | Ast.AssignOpTag(asgnop) -> option_default
+ | Ast.FixOpTag(fixop) -> option_default
+ | Ast.BinaryOpTag(binop) -> option_default
+ | Ast.ArithOpTag(arithop) -> option_default
+ | Ast.LogicalOpTag(logop) -> option_default
+ | Ast.DeclarationTag(decl) -> declaration decl
+ | Ast.InitTag(ini) -> initialiser ini
+ | Ast.StorageTag(stg) -> option_default
+ | Ast.IncFileTag(stg) -> option_default
+ | Ast.Rule_elemTag(rule) -> rule_elem rule
+ | Ast.StatementTag(rule) -> statement rule
+ | Ast.CaseLineTag(case) -> case_line case
+ | Ast.ConstVolTag(cv) -> option_default
+ | Ast.Token(tok,info) -> option_default
+ | Ast.Code(cd) -> top_level cd
+ | Ast.ExprDotsTag(ed) -> expression_dots ed
+ | Ast.ParamDotsTag(pd) -> parameter_dots pd
+ | Ast.StmtDotsTag(sd) -> statement_dots sd
+ | Ast.DeclDotsTag(sd) -> declaration_dots sd
+ | Ast.TypeCTag(ty) -> typeC ty
+ | Ast.ParamTag(param) -> parameterTypeDef param
+ | Ast.SgrepStartTag(tok) -> option_default
+ | Ast.SgrepEndTag(tok) -> option_default in
+ anyfn all_functions k a
+
+ and all_functions =
+ {combiner_ident = ident;
+ combiner_expression = expression;
+ combiner_fullType = fullType;
+ combiner_typeC = typeC;
+ combiner_declaration = declaration;
+ combiner_initialiser = initialiser;
+ combiner_parameter = parameterTypeDef;
+ combiner_parameter_list = parameter_dots;
+ combiner_rule_elem = rule_elem;
+ combiner_statement = statement;
+ combiner_case_line = case_line;
+ combiner_top_level = top_level;
+ combiner_anything = anything;
+ combiner_expression_dots = expression_dots;
+ combiner_statement_dots = statement_dots;
+ combiner_declaration_dots = declaration_dots} in
+ all_functions
+
+(* ---------------------------------------------------------------------- *)
+
+type 'a inout = 'a -> 'a (* for specifying the type of rebuilder *)
+
+type rebuilder =
+ {rebuilder_ident : Ast.ident inout;
+ rebuilder_expression : Ast.expression inout;
+ rebuilder_fullType : Ast.fullType inout;
+ rebuilder_typeC : Ast.typeC inout;
+ rebuilder_declaration : Ast.declaration inout;
+ rebuilder_initialiser : Ast.initialiser inout;
+ rebuilder_parameter : Ast.parameterTypeDef inout;
+ rebuilder_parameter_list : Ast.parameter_list inout;
+ rebuilder_statement : Ast.statement inout;
+ rebuilder_case_line : Ast.case_line inout;
+ rebuilder_rule_elem : Ast.rule_elem inout;
+ rebuilder_top_level : Ast.top_level inout;
+ rebuilder_expression_dots : Ast.expression Ast.dots inout;
+ rebuilder_statement_dots : Ast.statement Ast.dots inout;
+ rebuilder_declaration_dots : Ast.declaration Ast.dots inout;
+ rebuilder_define_param_dots : Ast.define_param Ast.dots inout;
+ rebuilder_define_param : Ast.define_param inout;
+ rebuilder_define_parameters : Ast.define_parameters inout;
+ rebuilder_anything : Ast.anything inout}
+
+type 'mc rmcode = 'mc Ast.mcode inout
+type 'cd rcode = rebuilder -> ('cd inout) -> 'cd inout
+
+
+let rebuilder
+ meta_mcode string_mcode const_mcode assign_mcode fix_mcode unary_mcode
+ binary_mcode cv_mcode base_mcode sign_mcode struct_mcode storage_mcode
+ inc_file_mcode
+ expdotsfn paramdotsfn stmtdotsfn decldotsfn
+ identfn exprfn ftfn tyfn initfn paramfn declfn rulefn stmtfn casefn
+ topfn anyfn =
+ let get_option f = function
+ Some x -> Some (f x)
+ | None -> None in
+ let rec expression_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map expression l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map expression l)
+ | Ast.STARS(l) -> Ast.STARS(List.map expression l)) in
+ expdotsfn all_functions k d
+
+ and parameter_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map parameterTypeDef l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map parameterTypeDef l)
+ | Ast.STARS(l) -> Ast.STARS(List.map parameterTypeDef l)) in
+ paramdotsfn all_functions k d
+
+ and statement_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map statement l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map statement l)
+ | Ast.STARS(l) -> Ast.STARS(List.map statement l)) in
+ stmtdotsfn all_functions k d
+
+ and declaration_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map declaration l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map declaration l)
+ | Ast.STARS(l) -> Ast.STARS(List.map declaration l)) in
+ decldotsfn all_functions k d
+
+ and ident i =
+ let k i =
+ Ast.rewrap i
+ (match Ast.unwrap i with
+ Ast.Id(name) -> Ast.Id(string_mcode name)
+ | Ast.MetaId(name,constraints,keep,inherited) ->
+ Ast.MetaId(meta_mcode name,constraints,keep,inherited)
+ | Ast.MetaFunc(name,constraints,keep,inherited) ->
+ Ast.MetaFunc(meta_mcode name,constraints,keep,inherited)
+ | Ast.MetaLocalFunc(name,constraints,keep,inherited) ->
+ Ast.MetaLocalFunc(meta_mcode name,constraints,keep,inherited)
+ | Ast.OptIdent(id) -> Ast.OptIdent(ident id)
+ | Ast.UniqueIdent(id) -> Ast.UniqueIdent(ident id)) in
+ identfn all_functions k i
+
+ and expression e =
+ let k e =
+ Ast.rewrap e
+ (match Ast.unwrap e with
+ Ast.Ident(id) -> Ast.Ident(ident id)
+ | Ast.Constant(const) -> Ast.Constant(const_mcode const)
+ | Ast.FunCall(fn,lp,args,rp) ->
+ Ast.FunCall(expression fn, string_mcode lp, expression_dots args,
+ string_mcode rp)
+ | Ast.Assignment(left,op,right,simple) ->
+ Ast.Assignment(expression left, assign_mcode op, expression right,
+ simple)
+ | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
+ Ast.CondExpr(expression exp1, string_mcode why,
+ get_option expression exp2, string_mcode colon,
+ expression exp3)
+ | Ast.Postfix(exp,op) -> Ast.Postfix(expression exp,fix_mcode op)
+ | Ast.Infix(exp,op) -> Ast.Infix(expression exp,fix_mcode op)
+ | Ast.Unary(exp,op) -> Ast.Unary(expression exp,unary_mcode op)
+ | Ast.Binary(left,op,right) ->
+ Ast.Binary(expression left, binary_mcode op, expression right)
+ | Ast.Nested(left,op,right) ->
+ Ast.Nested(expression left, binary_mcode op, expression right)
+ | Ast.Paren(lp,exp,rp) ->
+ Ast.Paren(string_mcode lp, expression exp, string_mcode rp)
+ | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
+ Ast.ArrayAccess(expression exp1, string_mcode lb, expression exp2,
+ string_mcode rb)
+ | Ast.RecordAccess(exp,pt,field) ->
+ Ast.RecordAccess(expression exp, string_mcode pt, ident field)
+ | Ast.RecordPtAccess(exp,ar,field) ->
+ Ast.RecordPtAccess(expression exp, string_mcode ar, ident field)
+ | Ast.Cast(lp,ty,rp,exp) ->
+ Ast.Cast(string_mcode lp, fullType ty, string_mcode rp,
+ expression exp)
+ | Ast.SizeOfExpr(szf,exp) ->
+ Ast.SizeOfExpr(string_mcode szf, expression exp)
+ | Ast.SizeOfType(szf,lp,ty,rp) ->
+ Ast.SizeOfType(string_mcode szf,string_mcode lp, fullType ty,
+ string_mcode rp)
+ | Ast.TypeExp(ty) -> Ast.TypeExp(fullType ty)
+ | Ast.MetaErr(name,constraints,keep,inherited) ->
+ Ast.MetaErr(meta_mcode name,constraints,keep,inherited)
+ | Ast.MetaExpr(name,constraints,keep,ty,form,inherited) ->
+ Ast.MetaExpr(meta_mcode name,constraints,keep,ty,form,inherited)
+ | Ast.MetaExprList(name,lenname_inh,keep,inherited) ->
+ Ast.MetaExprList(meta_mcode name,lenname_inh,keep,inherited)
+ | Ast.EComma(cm) -> Ast.EComma(string_mcode cm)
+ | Ast.DisjExpr(exp_list) -> Ast.DisjExpr(List.map expression exp_list)
+ | Ast.NestExpr(expr_dots,whencode,multi) ->
+ Ast.NestExpr(expression_dots expr_dots,
+ get_option expression whencode,multi)
+ | Ast.Edots(dots,whencode) ->
+ Ast.Edots(string_mcode dots,get_option expression whencode)
+ | Ast.Ecircles(dots,whencode) ->
+ Ast.Ecircles(string_mcode dots,get_option expression whencode)
+ | Ast.Estars(dots,whencode) ->
+ Ast.Estars(string_mcode dots,get_option expression whencode)
+ | Ast.OptExp(exp) -> Ast.OptExp(expression exp)
+ | Ast.UniqueExp(exp) -> Ast.UniqueExp(expression exp)) in
+ exprfn all_functions k e
+
+ and fullType ft =
+ let k ft =
+ Ast.rewrap ft
+ (match Ast.unwrap ft with
+ Ast.Type(cv,ty) -> Ast.Type (get_option cv_mcode cv, typeC ty)
+ | Ast.DisjType(types) -> Ast.DisjType(List.map fullType types)
+ | Ast.OptType(ty) -> Ast.OptType(fullType ty)
+ | Ast.UniqueType(ty) -> Ast.UniqueType(fullType ty)) in
+ ftfn all_functions k ft
+
+ and typeC ty =
+ let k ty =
+ Ast.rewrap ty
+ (match Ast.unwrap ty with
+ Ast.BaseType(ty,sgn) ->
+ Ast.BaseType (base_mcode ty,get_option sign_mcode sgn)
+ | Ast.ImplicitInt(sgn) -> Ast.ImplicitInt (sign_mcode sgn)
+ | Ast.Pointer(ty,star) ->
+ Ast.Pointer (fullType ty, string_mcode star)
+ | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ Ast.FunctionPointer(fullType ty,string_mcode lp1,string_mcode star,
+ string_mcode rp1,string_mcode lp2,
+ parameter_dots params,
+ string_mcode rp2)
+ | Ast.FunctionType(allminus,ty,lp,params,rp) ->
+ Ast.FunctionType(allminus,get_option fullType ty,string_mcode lp,
+ parameter_dots params,string_mcode rp)
+ | Ast.Array(ty,lb,size,rb) ->
+ Ast.Array(fullType ty, string_mcode lb,
+ get_option expression size, string_mcode rb)
+ | Ast.StructUnionName(kind,name) ->
+ Ast.StructUnionName (struct_mcode kind, get_option ident name)
+ | Ast.StructUnionDef(ty,lb,decls,rb) ->
+ Ast.StructUnionDef (fullType ty,
+ string_mcode lb, declaration_dots decls,
+ string_mcode rb)
+ | Ast.TypeName(name) -> Ast.TypeName(string_mcode name)
+ | Ast.MetaType(name,keep,inherited) ->
+ Ast.MetaType(meta_mcode name,keep,inherited)) in
+ tyfn all_functions k ty
+
+ and declaration d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.Init(stg,ty,id,eq,ini,sem) ->
+ Ast.Init(get_option storage_mcode stg, fullType ty, ident id,
+ string_mcode eq, initialiser ini, string_mcode sem)
+ | Ast.UnInit(stg,ty,id,sem) ->
+ Ast.UnInit(get_option storage_mcode stg, fullType ty, ident id,
+ string_mcode sem)
+ | Ast.MacroDecl(name,lp,args,rp,sem) ->
+ Ast.MacroDecl(ident name, string_mcode lp, expression_dots args,
+ string_mcode rp,string_mcode sem)
+ | Ast.TyDecl(ty,sem) -> Ast.TyDecl(fullType ty, string_mcode sem)
+ | Ast.Typedef(stg,ty,id,sem) ->
+ Ast.Typedef(string_mcode stg, fullType ty, typeC id,
+ string_mcode sem)
+ | Ast.DisjDecl(decls) -> Ast.DisjDecl(List.map declaration decls)
+ | Ast.Ddots(dots,whencode) ->
+ Ast.Ddots(string_mcode dots, get_option declaration whencode)
+ | Ast.MetaDecl(name,keep,inherited) ->
+ Ast.MetaDecl(meta_mcode name,keep,inherited)
+ | Ast.OptDecl(decl) -> Ast.OptDecl(declaration decl)
+ | Ast.UniqueDecl(decl) -> Ast.UniqueDecl(declaration decl)) in
+ declfn all_functions k d
+
+ and initialiser i =
+ let k i =
+ Ast.rewrap i
+ (match Ast.unwrap i with
+ Ast.InitExpr(exp) -> Ast.InitExpr(expression exp)
+ | Ast.InitList(lb,initlist,rb,whencode) ->
+ Ast.InitList(string_mcode lb, List.map initialiser initlist,
+ string_mcode rb, List.map initialiser whencode)
+ | Ast.InitGccDotName(dot,name,eq,ini) ->
+ Ast.InitGccDotName
+ (string_mcode dot, ident name, string_mcode eq, initialiser ini)
+ | Ast.InitGccName(name,eq,ini) ->
+ Ast.InitGccName(ident name, string_mcode eq, initialiser ini)
+ | Ast.InitGccIndex(lb,exp,rb,eq,ini) ->
+ Ast.InitGccIndex
+ (string_mcode lb, expression exp, string_mcode rb,
+ string_mcode eq, initialiser ini)
+ | Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ Ast.InitGccRange
+ (string_mcode lb, expression exp1, string_mcode dots,
+ expression exp2, string_mcode rb, string_mcode eq,
+ initialiser ini)
+ | Ast.IComma(cm) -> Ast.IComma(string_mcode cm)
+ | Ast.OptIni(i) -> Ast.OptIni(initialiser i)
+ | Ast.UniqueIni(i) -> Ast.UniqueIni(initialiser i)) in
+ initfn all_functions k i
+
+ and parameterTypeDef p =
+ let k p =
+ Ast.rewrap p
+ (match Ast.unwrap p with
+ Ast.VoidParam(ty) -> Ast.VoidParam(fullType ty)
+ | Ast.Param(ty,id) -> Ast.Param(fullType ty, get_option ident id)
+ | Ast.MetaParam(name,keep,inherited) ->
+ Ast.MetaParam(meta_mcode name,keep,inherited)
+ | Ast.MetaParamList(name,lenname_inh,keep,inherited) ->
+ Ast.MetaParamList(meta_mcode name,lenname_inh,keep,inherited)
+ | Ast.PComma(cm) -> Ast.PComma(string_mcode cm)
+ | Ast.Pdots(dots) -> Ast.Pdots(string_mcode dots)
+ | Ast.Pcircles(dots) -> Ast.Pcircles(string_mcode dots)
+ | Ast.OptParam(param) -> Ast.OptParam(parameterTypeDef param)
+ | Ast.UniqueParam(param) -> Ast.UniqueParam(parameterTypeDef param)) in
+ paramfn all_functions k p
+
+ and rule_elem re =
+ let k re =
+ Ast.rewrap re
+ (match Ast.unwrap re with
+ Ast.FunHeader(bef,allminus,fi,name,lp,params,rp) ->
+ Ast.FunHeader(bef,allminus,List.map fninfo fi,ident name,
+ string_mcode lp, parameter_dots params,
+ string_mcode rp)
+ | Ast.Decl(bef,allminus,decl) ->
+ Ast.Decl(bef,allminus,declaration decl)
+ | Ast.SeqStart(brace) -> Ast.SeqStart(string_mcode brace)
+ | Ast.SeqEnd(brace) -> Ast.SeqEnd(string_mcode brace)
+ | Ast.ExprStatement(exp,sem) ->
+ Ast.ExprStatement (expression exp, string_mcode sem)
+ | Ast.IfHeader(iff,lp,exp,rp) ->
+ Ast.IfHeader(string_mcode iff, string_mcode lp, expression exp,
+ string_mcode rp)
+ | Ast.Else(els) -> Ast.Else(string_mcode els)
+ | Ast.WhileHeader(whl,lp,exp,rp) ->
+ Ast.WhileHeader(string_mcode whl, string_mcode lp, expression exp,
+ string_mcode rp)
+ | Ast.DoHeader(d) -> Ast.DoHeader(string_mcode d)
+ | Ast.WhileTail(whl,lp,exp,rp,sem) ->
+ Ast.WhileTail(string_mcode whl, string_mcode lp, expression exp,
+ string_mcode rp, string_mcode sem)
+ | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
+ Ast.ForHeader(string_mcode fr, string_mcode lp,
+ get_option expression e1, string_mcode sem1,
+ get_option expression e2, string_mcode sem2,
+ get_option expression e3, string_mcode rp)
+ | Ast.IteratorHeader(whl,lp,args,rp) ->
+ Ast.IteratorHeader(ident whl, string_mcode lp,
+ expression_dots args, string_mcode rp)
+ | Ast.SwitchHeader(switch,lp,exp,rp) ->
+ Ast.SwitchHeader(string_mcode switch, string_mcode lp,
+ expression exp, string_mcode rp)
+ | Ast.Break(br,sem) ->
+ Ast.Break(string_mcode br, string_mcode sem)
+ | Ast.Continue(cont,sem) ->
+ Ast.Continue(string_mcode cont, string_mcode sem)
+ | Ast.Label(l,dd) -> Ast.Label(ident l, string_mcode dd)
+ | Ast.Goto(goto,l,sem) ->
+ Ast.Goto(string_mcode goto,ident l,string_mcode sem)
+ | Ast.Return(ret,sem) ->
+ Ast.Return(string_mcode ret, string_mcode sem)
+ | Ast.ReturnExpr(ret,exp,sem) ->
+ Ast.ReturnExpr(string_mcode ret, expression exp, string_mcode sem)
+ | Ast.MetaStmt(name,keep,seqible,inherited) ->
+ Ast.MetaStmt(meta_mcode name,keep,seqible,inherited)
+ | Ast.MetaStmtList(name,keep,inherited) ->
+ Ast.MetaStmtList(meta_mcode name,keep,inherited)
+ | Ast.MetaRuleElem(name,keep,inherited) ->
+ Ast.MetaRuleElem(meta_mcode name,keep,inherited)
+ | Ast.Exp(exp) -> Ast.Exp(expression exp)
+ | Ast.TopExp(exp) -> Ast.TopExp(expression exp)
+ | Ast.Ty(ty) -> Ast.Ty(fullType ty)
+ | Ast.Include(inc,name) ->
+ Ast.Include(string_mcode inc,inc_file_mcode name)
+ | Ast.DefineHeader(def,id,params) ->
+ Ast.DefineHeader(string_mcode def,ident id,
+ define_parameters params)
+ | Ast.Default(def,colon) ->
+ Ast.Default(string_mcode def,string_mcode colon)
+ | Ast.Case(case,exp,colon) ->
+ Ast.Case(string_mcode case,expression exp,string_mcode colon)
+ | Ast.DisjRuleElem(res) -> Ast.DisjRuleElem(List.map rule_elem res)) in
+ rulefn all_functions k re
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ Ast.rewrap p
+ (match Ast.unwrap p with
+ Ast.NoParams -> Ast.NoParams
+ | Ast.DParams(lp,params,rp) ->
+ Ast.DParams(string_mcode lp,define_param_dots params,
+ string_mcode rp)) in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map define_param l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map define_param l)
+ | Ast.STARS(l) -> Ast.STARS(List.map define_param l)) in
+ k d
+
+ and define_param p =
+ let k p =
+ Ast.rewrap p
+ (match Ast.unwrap p with
+ Ast.DParam(id) -> Ast.DParam(ident id)
+ | Ast.DPComma(comma) -> Ast.DPComma(string_mcode comma)
+ | Ast.DPdots(d) -> Ast.DPdots(string_mcode d)
+ | Ast.DPcircles(c) -> Ast.DPcircles(string_mcode c)
+ | Ast.OptDParam(dp) -> Ast.OptDParam(define_param dp)
+ | Ast.UniqueDParam(dp) -> Ast.UniqueDParam(define_param dp)) in
+ k p
+
+ and process_bef_aft s =
+ Ast.set_dots_bef_aft
+ (match Ast.get_dots_bef_aft s with
+ Ast.NoDots -> Ast.NoDots
+ | Ast.DroppingBetweenDots(stm,ind) ->
+ Ast.DroppingBetweenDots(statement stm,ind)
+ | Ast.AddingBetweenDots(stm,ind) ->
+ Ast.AddingBetweenDots(statement stm,ind))
+ s
+
+ and statement s =
+ let k s =
+ Ast.rewrap s
+ (match Ast.unwrap s with
+ Ast.Seq(lbrace,decls,body,rbrace) ->
+ Ast.Seq(rule_elem lbrace, statement_dots decls,
+ statement_dots body, rule_elem rbrace)
+ | Ast.IfThen(header,branch,aft) ->
+ Ast.IfThen(rule_elem header, statement branch,aft)
+ | Ast.IfThenElse(header,branch1,els,branch2,aft) ->
+ Ast.IfThenElse(rule_elem header, statement branch1, rule_elem els,
+ statement branch2, aft)
+ | Ast.While(header,body,aft) ->
+ Ast.While(rule_elem header, statement body, aft)
+ | Ast.Do(header,body,tail) ->
+ Ast.Do(rule_elem header, statement body, rule_elem tail)
+ | Ast.For(header,body,aft) ->
+ Ast.For(rule_elem header, statement body, aft)
+ | Ast.Iterator(header,body,aft) ->
+ Ast.Iterator(rule_elem header, statement body, aft)
+ | Ast.Switch(header,lb,cases,rb) ->
+ Ast.Switch(rule_elem header,rule_elem lb,
+ List.map case_line cases,rule_elem rb)
+ | Ast.Atomic(re) -> Ast.Atomic(rule_elem re)
+ | Ast.Disj(stmt_dots_list) ->
+ Ast.Disj (List.map statement_dots stmt_dots_list)
+ | Ast.Nest(stmt_dots,whn,multi,bef,aft) ->
+ Ast.Nest(statement_dots stmt_dots,
+ List.map (whencode statement_dots statement) whn,
+ multi,bef,aft)
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ Ast.FunDecl(rule_elem header,rule_elem lbrace,
+ statement_dots decls,
+ statement_dots body, rule_elem rbrace)
+ | Ast.Define(header,body) ->
+ Ast.Define(rule_elem header,statement_dots body)
+ | Ast.Dots(d,whn,bef,aft) ->
+ Ast.Dots(string_mcode d,
+ List.map (whencode statement_dots statement) whn,bef,aft)
+ | Ast.Circles(d,whn,bef,aft) ->
+ Ast.Circles(string_mcode d,
+ List.map (whencode statement_dots statement) whn,
+ bef,aft)
+ | Ast.Stars(d,whn,bef,aft) ->
+ Ast.Stars(string_mcode d,
+ List.map (whencode statement_dots statement) whn,bef,aft)
+ | Ast.OptStm(stmt) -> Ast.OptStm(statement stmt)
+ | Ast.UniqueStm(stmt) -> Ast.UniqueStm(statement stmt)) in
+ let s = stmtfn all_functions k s in
+ (* better to do this after, in case there is an equality test on the whole
+ statement, eg in free_vars. equality test would require that this
+ subterm not already be changed *)
+ process_bef_aft s
+
+ and fninfo = function
+ Ast.FStorage(stg) -> Ast.FStorage(storage_mcode stg)
+ | Ast.FType(ty) -> Ast.FType(fullType ty)
+ | Ast.FInline(inline) -> Ast.FInline(string_mcode inline)
+ | Ast.FAttr(attr) -> Ast.FAttr(string_mcode attr)
+
+ and whencode notfn alwaysfn = function
+ Ast.WhenNot a -> Ast.WhenNot (notfn a)
+ | Ast.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x)
+
+ and case_line c =
+ let k c =
+ Ast.rewrap c
+ (match Ast.unwrap c with
+ Ast.CaseLine(header,code) ->
+ Ast.CaseLine(rule_elem header,statement_dots code)
+ | Ast.OptCase(case) -> Ast.OptCase(case_line case)) in
+ casefn all_functions k c
+
+ and top_level t =
+ let k t =
+ Ast.rewrap t
+ (match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) ->
+ Ast.FILEINFO (string_mcode old_file, string_mcode new_file)
+ | Ast.DECL(stmt) -> Ast.DECL(statement stmt)
+ | Ast.CODE(stmt_dots) -> Ast.CODE(statement_dots stmt_dots)
+ | Ast.ERRORWORDS(exps) -> Ast.ERRORWORDS (List.map expression exps)) in
+ topfn all_functions k t
+
+ and anything a =
+ let k = function
+ (*in many cases below, the thing is not even mcode, so we do nothing*)
+ Ast.FullTypeTag(ft) -> Ast.FullTypeTag(fullType ft)
+ | Ast.BaseTypeTag(bt) as x -> x
+ | Ast.StructUnionTag(su) as x -> x
+ | Ast.SignTag(sgn) as x -> x
+ | Ast.IdentTag(id) -> Ast.IdentTag(ident id)
+ | Ast.ExpressionTag(exp) -> Ast.ExpressionTag(expression exp)
+ | Ast.ConstantTag(cst) as x -> x
+ | Ast.UnaryOpTag(unop) as x -> x
+ | Ast.AssignOpTag(asgnop) as x -> x
+ | Ast.FixOpTag(fixop) as x -> x
+ | Ast.BinaryOpTag(binop) as x -> x
+ | Ast.ArithOpTag(arithop) as x -> x
+ | Ast.LogicalOpTag(logop) as x -> x
+ | Ast.InitTag(decl) -> Ast.InitTag(initialiser decl)
+ | Ast.DeclarationTag(decl) -> Ast.DeclarationTag(declaration decl)
+ | Ast.StorageTag(stg) as x -> x
+ | Ast.IncFileTag(stg) as x -> x
+ | Ast.Rule_elemTag(rule) -> Ast.Rule_elemTag(rule_elem rule)
+ | Ast.StatementTag(rule) -> Ast.StatementTag(statement rule)
+ | Ast.CaseLineTag(case) -> Ast.CaseLineTag(case_line case)
+ | Ast.ConstVolTag(cv) as x -> x
+ | Ast.Token(tok,info) as x -> x
+ | Ast.Code(cd) -> Ast.Code(top_level cd)
+ | Ast.ExprDotsTag(ed) -> Ast.ExprDotsTag(expression_dots ed)
+ | Ast.ParamDotsTag(pd) -> Ast.ParamDotsTag(parameter_dots pd)
+ | Ast.StmtDotsTag(sd) -> Ast.StmtDotsTag(statement_dots sd)
+ | Ast.DeclDotsTag(sd) -> Ast.DeclDotsTag(declaration_dots sd)
+ | Ast.TypeCTag(ty) -> Ast.TypeCTag(typeC ty)
+ | Ast.ParamTag(param) -> Ast.ParamTag(parameterTypeDef param)
+ | Ast.SgrepStartTag(tok) as x -> x
+ | Ast.SgrepEndTag(tok) as x -> x in
+ anyfn all_functions k a
+
+ and all_functions =
+ {rebuilder_ident = ident;
+ rebuilder_expression = expression;
+ rebuilder_fullType= fullType;
+ rebuilder_typeC = typeC;
+ rebuilder_declaration = declaration;
+ rebuilder_initialiser = initialiser;
+ rebuilder_parameter = parameterTypeDef;
+ rebuilder_parameter_list = parameter_dots;
+ rebuilder_rule_elem = rule_elem;
+ rebuilder_statement = statement;
+ rebuilder_case_line = case_line;
+ rebuilder_top_level = top_level;
+ rebuilder_expression_dots = expression_dots;
+ rebuilder_statement_dots = statement_dots;
+ rebuilder_declaration_dots = declaration_dots;
+ rebuilder_define_param_dots = define_param_dots;
+ rebuilder_define_param = define_param;
+ rebuilder_define_parameters = define_parameters;
+ rebuilder_anything = anything} in
+ all_functions
+
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+
+(* --------------------------------------------------------------------- *)
+(* Generic traversal: combiner *)
+(* parameters:
+ combining function
+ treatment of: mcode, identifiers, expressions, fullTypes, types,
+ declarations, statements, toplevels
+ default value for options *)
+
+type 'a combiner =
+ {combiner_ident : Ast.ident -> 'a;
+ combiner_expression : Ast.expression -> 'a;
+ combiner_fullType : Ast.fullType -> 'a;
+ combiner_typeC : Ast.typeC -> 'a;
+ combiner_declaration : Ast.declaration -> 'a;
+ combiner_initialiser : Ast.initialiser -> 'a;
+ combiner_parameter : Ast.parameterTypeDef -> 'a;
+ combiner_parameter_list : Ast.parameter_list -> 'a;
+ combiner_rule_elem : Ast.rule_elem -> 'a;
+ combiner_statement : Ast.statement -> 'a;
+ combiner_case_line : Ast.case_line -> 'a;
+ combiner_top_level : Ast.top_level -> 'a;
+ combiner_anything : Ast.anything -> 'a;
+ combiner_expression_dots : Ast.expression Ast.dots -> 'a;
+ combiner_statement_dots : Ast.statement Ast.dots -> 'a;
+ combiner_declaration_dots : Ast.declaration Ast.dots -> 'a}
+
+type ('mc,'a) cmcode = 'a combiner -> 'mc Ast_cocci.mcode -> 'a
+type ('cd,'a) ccode = 'a combiner -> ('cd -> 'a) -> 'cd -> 'a
+
+
+let combiner bind option_default
+ meta_mcodefn string_mcodefn const_mcodefn assign_mcodefn fix_mcodefn
+ unary_mcodefn binary_mcodefn
+ cv_mcodefn base_mcodefn sign_mcodefn struct_mcodefn storage_mcodefn
+ inc_file_mcodefn
+ expdotsfn paramdotsfn stmtdotsfn decldotsfn
+ identfn exprfn ftfn tyfn initfn paramfn declfn rulefn stmtfn casefn
+ topfn anyfn =
+ let multibind l =
+ let rec loop = function
+ [] -> option_default
+ | [x] -> x
+ | x::xs -> bind x (loop xs) in
+ loop l in
+ let get_option f = function
+ Some x -> f x
+ | None -> option_default in
+
+ let rec meta_mcode x = meta_mcodefn all_functions x
+ and string_mcode x = string_mcodefn all_functions x
+ and const_mcode x = const_mcodefn all_functions x
+ and assign_mcode x = assign_mcodefn all_functions x
+ and fix_mcode x = fix_mcodefn all_functions x
+ and unary_mcode x = unary_mcodefn all_functions x
+ and binary_mcode x = binary_mcodefn all_functions x
+ and cv_mcode x = cv_mcodefn all_functions x
+ and base_mcode x = base_mcodefn all_functions x
+ and sign_mcode x = sign_mcodefn all_functions x
+ and struct_mcode x = struct_mcodefn all_functions x
+ and storage_mcode x = storage_mcodefn all_functions x
+ and inc_file_mcode x = inc_file_mcodefn all_functions x
+
+ and expression_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map expression l) in
+ expdotsfn all_functions k d
+
+ and parameter_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map parameterTypeDef l) in
+ paramdotsfn all_functions k d
+
+ and statement_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map statement l) in
+ stmtdotsfn all_functions k d
+
+ and declaration_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map declaration l) in
+ decldotsfn all_functions k d
+
+ and ident i =
+ let k i =
+ match Ast.unwrap i with
+ Ast.Id(name) -> string_mcode name
+ | Ast.MetaId(name,_,_,_) -> meta_mcode name
+ | Ast.MetaFunc(name,_,_,_) -> meta_mcode name
+ | Ast.MetaLocalFunc(name,_,_,_) -> meta_mcode name
+ | Ast.OptIdent(id) -> ident id
+ | Ast.UniqueIdent(id) -> ident id in
+ identfn all_functions k i
+
+ and expression e =
+ let k e =
+ match Ast.unwrap e with
+ Ast.Ident(id) -> ident id
+ | Ast.Constant(const) -> const_mcode const
+ | Ast.FunCall(fn,lp,args,rp) ->
+ multibind [expression fn; string_mcode lp; expression_dots args;
+ string_mcode rp]
+ | Ast.Assignment(left,op,right,simple) ->
+ multibind [expression left; assign_mcode op; expression right]
+ | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
+ multibind [expression exp1; string_mcode why;
+ get_option expression exp2; string_mcode colon;
+ expression exp3]
+ | Ast.Postfix(exp,op) -> bind (expression exp) (fix_mcode op)
+ | Ast.Infix(exp,op) -> bind (fix_mcode op) (expression exp)
+ | Ast.Unary(exp,op) -> bind (unary_mcode op) (expression exp)
+ | Ast.Binary(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast.Nested(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast.Paren(lp,exp,rp) ->
+ multibind [string_mcode lp; expression exp; string_mcode rp]
+ | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
+ multibind
+ [expression exp1; string_mcode lb; expression exp2;
+ string_mcode rb]
+ | Ast.RecordAccess(exp,pt,field) ->
+ multibind [expression exp; string_mcode pt; ident field]
+ | Ast.RecordPtAccess(exp,ar,field) ->
+ multibind [expression exp; string_mcode ar; ident field]
+ | Ast.Cast(lp,ty,rp,exp) ->
+ multibind
+ [string_mcode lp; fullType ty; string_mcode rp; expression exp]
+ | Ast.SizeOfExpr(szf,exp) ->
+ multibind [string_mcode szf; expression exp]
+ | Ast.SizeOfType(szf,lp,ty,rp) ->
+ multibind
+ [string_mcode szf; string_mcode lp; fullType ty; string_mcode rp]
+ | Ast.TypeExp(ty) -> fullType ty
+ | Ast.MetaErr(name,_,_,_)
+ | Ast.MetaExpr(name,_,_,_,_,_)
+ | Ast.MetaExprList(name,_,_,_) -> meta_mcode name
+ | Ast.EComma(cm) -> string_mcode cm
+ | Ast.DisjExpr(exp_list) -> multibind (List.map expression exp_list)
+ | Ast.NestExpr(expr_dots,whencode,multi) ->
+ bind (expression_dots expr_dots) (get_option expression whencode)
+ | Ast.Edots(dots,whencode) | Ast.Ecircles(dots,whencode)
+ | Ast.Estars(dots,whencode) ->
+ bind (string_mcode dots) (get_option expression whencode)
+ | Ast.OptExp(exp) | Ast.UniqueExp(exp) ->
+ expression exp in
+ exprfn all_functions k e
+
+ and fullType ft =
+ let k ft =
+ match Ast.unwrap ft with
+ Ast.Type(cv,ty) -> bind (get_option cv_mcode cv) (typeC ty)
+ | Ast.DisjType(types) -> multibind (List.map fullType types)
+ | Ast.OptType(ty) -> fullType ty
+ | Ast.UniqueType(ty) -> fullType ty in
+ ftfn all_functions k ft
+
+ and function_pointer (ty,lp1,star,rp1,lp2,params,rp2) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind
+ ([fullType ty; string_mcode lp1; string_mcode star] @ extra @
+ [string_mcode rp1;
+ string_mcode lp2; parameter_dots params; string_mcode rp2])
+
+ and function_type (ty,lp1,params,rp1) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind
+ ([get_option fullType ty] @ extra @
+ [string_mcode lp1; parameter_dots params; string_mcode rp1])
+
+ and array_type (ty,lb,size,rb) extra =
+ multibind
+ ([fullType ty] @ extra @
+ [string_mcode lb; get_option expression size; string_mcode rb])
+
+ and typeC ty =
+ let k ty =
+ match Ast.unwrap ty with
+ Ast.BaseType(ty,sgn) ->
+ bind (get_option sign_mcode sgn) (base_mcode ty)
+ | Ast.ImplicitInt(sgn) -> sign_mcode sgn
+ | Ast.Pointer(ty,star) ->
+ bind (fullType ty) (string_mcode star)
+ | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) []
+ | Ast.FunctionType (_,ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) []
+ | Ast.Array(ty,lb,size,rb) -> array_type (ty,lb,size,rb) []
+ | Ast.StructUnionName(kind,name) ->
+ bind (struct_mcode kind) (get_option ident name)
+ | Ast.StructUnionDef(ty,lb,decls,rb) ->
+ multibind
+ [fullType ty; string_mcode lb; declaration_dots decls;
+ string_mcode rb]
+ | Ast.TypeName(name) -> string_mcode name
+ | Ast.MetaType(name,_,_) -> meta_mcode name in
+ tyfn all_functions k ty
+
+ and named_type ty id =
+ match Ast.unwrap ty with
+ Ast.Type(None,ty1) ->
+ (match Ast.unwrap ty1 with
+ Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) [ident id]
+ | Ast.FunctionType(_,ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) [ident id]
+ | Ast.Array(ty,lb,size,rb) -> array_type (ty,lb,size,rb) [ident id]
+ | _ -> bind (fullType ty) (ident id))
+ | _ -> bind (fullType ty) (ident id)
+
+ and declaration d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.Init(stg,ty,id,eq,ini,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id)
+ (multibind
+ [string_mcode eq; initialiser ini; string_mcode sem]))
+ | Ast.UnInit(stg,ty,id,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id) (string_mcode sem))
+ | Ast.MacroDecl(name,lp,args,rp,sem) ->
+ multibind
+ [ident name; string_mcode lp; expression_dots args;
+ string_mcode rp; string_mcode sem]
+ | Ast.TyDecl(ty,sem) -> bind (fullType ty) (string_mcode sem)
+ | Ast.Typedef(stg,ty,id,sem) ->
+ bind (string_mcode stg)
+ (bind (fullType ty) (bind (typeC id) (string_mcode sem)))
+ | Ast.DisjDecl(decls) -> multibind (List.map declaration decls)
+ | Ast.Ddots(dots,whencode) ->
+ bind (string_mcode dots) (get_option declaration whencode)
+ | Ast.MetaDecl(name,_,_) -> meta_mcode name
+ | Ast.OptDecl(decl) -> declaration decl
+ | Ast.UniqueDecl(decl) -> declaration decl in
+ declfn all_functions k d
+
+ and initialiser i =
+ let k i =
+ match Ast.unwrap i with
+ Ast.InitExpr(exp) -> expression exp
+ | Ast.InitList(lb,initlist,rb,whencode) ->
+ multibind
+ [string_mcode lb;
+ multibind (List.map initialiser initlist);
+ string_mcode rb;
+ multibind (List.map initialiser whencode)]
+ | Ast.InitGccDotName(dot,name,eq,ini) ->
+ multibind
+ [string_mcode dot; ident name; string_mcode eq; initialiser ini]
+ | Ast.InitGccName(name,eq,ini) ->
+ multibind [ident name; string_mcode eq; initialiser ini]
+ | Ast.InitGccIndex(lb,exp,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp; string_mcode rb;
+ string_mcode eq; initialiser ini]
+ | Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp1; string_mcode dots;
+ expression exp2; string_mcode rb; string_mcode eq;
+ initialiser ini]
+ | Ast.IComma(cm) -> string_mcode cm
+ | Ast.OptIni(i) -> initialiser i
+ | Ast.UniqueIni(i) -> initialiser i in
+ initfn all_functions k i
+
+ and parameterTypeDef p =
+ let k p =
+ match Ast.unwrap p with
+ Ast.VoidParam(ty) -> fullType ty
+ | Ast.Param(ty,Some id) -> named_type ty id
+ | Ast.Param(ty,None) -> fullType ty
+ | Ast.MetaParam(name,_,_) -> meta_mcode name
+ | Ast.MetaParamList(name,_,_,_) -> meta_mcode name
+ | Ast.PComma(cm) -> string_mcode cm
+ | Ast.Pdots(dots) -> string_mcode dots
+ | Ast.Pcircles(dots) -> string_mcode dots
+ | Ast.OptParam(param) -> parameterTypeDef param
+ | Ast.UniqueParam(param) -> parameterTypeDef param in
+ paramfn all_functions k p
+
+ and rule_elem re =
+ let k re =
+ match Ast.unwrap re with
+ Ast.FunHeader(_,_,fi,name,lp,params,rp) ->
+ multibind
+ ((List.map fninfo fi) @
+ [ident name;string_mcode lp;parameter_dots params;
+ string_mcode rp])
+ | Ast.Decl(_,_,decl) -> declaration decl
+ | Ast.SeqStart(brace) -> string_mcode brace
+ | Ast.SeqEnd(brace) -> string_mcode brace
+ | Ast.ExprStatement(exp,sem) ->
+ bind (expression exp) (string_mcode sem)
+ | Ast.IfHeader(iff,lp,exp,rp) ->
+ multibind [string_mcode iff; string_mcode lp; expression exp;
+ string_mcode rp]
+ | Ast.Else(els) -> string_mcode els
+ | Ast.WhileHeader(whl,lp,exp,rp) ->
+ multibind [string_mcode whl; string_mcode lp; expression exp;
+ string_mcode rp]
+ | Ast.DoHeader(d) -> string_mcode d
+ | Ast.WhileTail(whl,lp,exp,rp,sem) ->
+ multibind [string_mcode whl; string_mcode lp; expression exp;
+ string_mcode rp; string_mcode sem]
+ | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
+ multibind [string_mcode fr; string_mcode lp;
+ get_option expression e1; string_mcode sem1;
+ get_option expression e2; string_mcode sem2;
+ get_option expression e3; string_mcode rp]
+ | Ast.IteratorHeader(nm,lp,args,rp) ->
+ multibind [ident nm; string_mcode lp;
+ expression_dots args; string_mcode rp]
+ | Ast.SwitchHeader(switch,lp,exp,rp) ->
+ multibind [string_mcode switch; string_mcode lp; expression exp;
+ string_mcode rp]
+ | Ast.Break(br,sem) -> bind (string_mcode br) (string_mcode sem)
+ | Ast.Continue(cont,sem) -> bind (string_mcode cont) (string_mcode sem)
+ | Ast.Label(l,dd) -> bind (ident l) (string_mcode dd)
+ | Ast.Goto(goto,l,sem) ->
+ bind (string_mcode goto) (bind (ident l) (string_mcode sem))
+ | Ast.Return(ret,sem) -> bind (string_mcode ret) (string_mcode sem)
+ | Ast.ReturnExpr(ret,exp,sem) ->
+ multibind [string_mcode ret; expression exp; string_mcode sem]
+ | Ast.MetaStmt(name,_,_,_) -> meta_mcode name
+ | Ast.MetaStmtList(name,_,_) -> meta_mcode name
+ | Ast.MetaRuleElem(name,_,_) -> meta_mcode name
+ | Ast.Exp(exp) -> expression exp
+ | Ast.TopExp(exp) -> expression exp
+ | Ast.Ty(ty) -> fullType ty
+ | Ast.Include(inc,name) -> bind (string_mcode inc) (inc_file_mcode name)
+ | Ast.DefineHeader(def,id,params) ->
+ multibind [string_mcode def; ident id; define_parameters params]
+ | Ast.Default(def,colon) -> bind (string_mcode def) (string_mcode colon)
+ | Ast.Case(case,exp,colon) ->
+ multibind [string_mcode case; expression exp; string_mcode colon]
+ | Ast.DisjRuleElem(res) -> multibind (List.map rule_elem res) in
+ rulefn all_functions k re
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ match Ast.unwrap p with
+ Ast.NoParams -> option_default
+ | Ast.DParams(lp,params,rp) ->
+ multibind
+ [string_mcode lp; define_param_dots params; string_mcode rp] in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ match Ast.unwrap d with
+ Ast.DOTS(l) | Ast.CIRCLES(l) | Ast.STARS(l) ->
+ multibind (List.map define_param l) in
+ k d
+
+ and define_param p =
+ let k p =
+ match Ast.unwrap p with
+ Ast.DParam(id) -> ident id
+ | Ast.DPComma(comma) -> string_mcode comma
+ | Ast.DPdots(d) -> string_mcode d
+ | Ast.DPcircles(c) -> string_mcode c
+ | Ast.OptDParam(dp) -> define_param dp
+ | Ast.UniqueDParam(dp) -> define_param dp in
+ k p
+
+ (* discard the result, because the statement is assumed to be already
+ represented elsewhere in the code *)
+ and process_bef_aft s =
+ match Ast.get_dots_bef_aft s with
+ Ast.NoDots -> ()
+ | Ast.DroppingBetweenDots(stm,ind) -> let _ = statement stm in ()
+ | Ast.AddingBetweenDots(stm,ind) -> let _ = statement stm in ()
+
+ and statement s =
+ process_bef_aft s;
+ let k s =
+ match Ast.unwrap s with
+ Ast.Seq(lbrace,decls,body,rbrace) ->
+ multibind [rule_elem lbrace; statement_dots decls;
+ statement_dots body; rule_elem rbrace]
+ | Ast.IfThen(header,branch,_) ->
+ multibind [rule_elem header; statement branch]
+ | Ast.IfThenElse(header,branch1,els,branch2,_) ->
+ multibind [rule_elem header; statement branch1; rule_elem els;
+ statement branch2]
+ | Ast.While(header,body,_) ->
+ multibind [rule_elem header; statement body]
+ | Ast.Do(header,body,tail) ->
+ multibind [rule_elem header; statement body; rule_elem tail]
+ | Ast.For(header,body,_) -> multibind [rule_elem header; statement body]
+ | Ast.Iterator(header,body,_) ->
+ multibind [rule_elem header; statement body]
+ | Ast.Switch(header,lb,cases,rb) ->
+ multibind [rule_elem header;rule_elem lb;
+ multibind (List.map case_line cases);
+ rule_elem rb]
+ | Ast.Atomic(re) -> rule_elem re
+ | Ast.Disj(stmt_dots_list) ->
+ multibind (List.map statement_dots stmt_dots_list)
+ | Ast.Nest(stmt_dots,whn,_,_,_) ->
+ bind (statement_dots stmt_dots)
+ (multibind (List.map (whencode statement_dots statement) whn))
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ multibind [rule_elem header; rule_elem lbrace;
+ statement_dots decls; statement_dots body;
+ rule_elem rbrace]
+ | Ast.Define(header,body) ->
+ bind (rule_elem header) (statement_dots body)
+ | Ast.Dots(d,whn,_,_) | Ast.Circles(d,whn,_,_) | Ast.Stars(d,whn,_,_) ->
+ bind (string_mcode d)
+ (multibind (List.map (whencode statement_dots statement) whn))
+ | Ast.OptStm(stmt) | Ast.UniqueStm(stmt) ->
+ statement stmt in
+ stmtfn all_functions k s
+
+ and fninfo = function
+ Ast.FStorage(stg) -> storage_mcode stg
+ | Ast.FType(ty) -> fullType ty
+ | Ast.FInline(inline) -> string_mcode inline
+ | Ast.FAttr(attr) -> string_mcode attr
+
+ and whencode notfn alwaysfn = function
+ Ast.WhenNot a -> notfn a
+ | Ast.WhenAlways a -> alwaysfn a
+ | Ast.WhenModifier(_) -> option_default
+ | Ast.WhenNotTrue(e) -> rule_elem e
+ | Ast.WhenNotFalse(e) -> rule_elem e
+
+ and case_line c =
+ let k c =
+ match Ast.unwrap c with
+ Ast.CaseLine(header,code) ->
+ bind (rule_elem header) (statement_dots code)
+ | Ast.OptCase(case) -> case_line case in
+ casefn all_functions k c
+
+ and top_level t =
+ let k t =
+ match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) ->
+ bind (string_mcode old_file) (string_mcode new_file)
+ | Ast.DECL(stmt) -> statement stmt
+ | Ast.CODE(stmt_dots) -> statement_dots stmt_dots
+ | Ast.ERRORWORDS(exps) -> multibind (List.map expression exps) in
+ topfn all_functions k t
+
+ and anything a =
+ let k = function
+ (*in many cases below, the thing is not even mcode, so we do nothing*)
+ Ast.FullTypeTag(ft) -> fullType ft
+ | Ast.BaseTypeTag(bt) -> option_default
+ | Ast.StructUnionTag(su) -> option_default
+ | Ast.SignTag(sgn) -> option_default
+ | Ast.IdentTag(id) -> ident id
+ | Ast.ExpressionTag(exp) -> expression exp
+ | Ast.ConstantTag(cst) -> option_default
+ | Ast.UnaryOpTag(unop) -> option_default
+ | Ast.AssignOpTag(asgnop) -> option_default
+ | Ast.FixOpTag(fixop) -> option_default
+ | Ast.BinaryOpTag(binop) -> option_default
+ | Ast.ArithOpTag(arithop) -> option_default
+ | Ast.LogicalOpTag(logop) -> option_default
+ | Ast.DeclarationTag(decl) -> declaration decl
+ | Ast.InitTag(ini) -> initialiser ini
+ | Ast.StorageTag(stg) -> option_default
+ | Ast.IncFileTag(stg) -> option_default
+ | Ast.Rule_elemTag(rule) -> rule_elem rule
+ | Ast.StatementTag(rule) -> statement rule
+ | Ast.CaseLineTag(case) -> case_line case
+ | Ast.ConstVolTag(cv) -> option_default
+ | Ast.Token(tok,info) -> option_default
+ | Ast.Code(cd) -> top_level cd
+ | Ast.ExprDotsTag(ed) -> expression_dots ed
+ | Ast.ParamDotsTag(pd) -> parameter_dots pd
+ | Ast.StmtDotsTag(sd) -> statement_dots sd
+ | Ast.DeclDotsTag(sd) -> declaration_dots sd
+ | Ast.TypeCTag(ty) -> typeC ty
+ | Ast.ParamTag(param) -> parameterTypeDef param
+ | Ast.SgrepStartTag(tok) -> option_default
+ | Ast.SgrepEndTag(tok) -> option_default in
+ anyfn all_functions k a
+
+ and all_functions =
+ {combiner_ident = ident;
+ combiner_expression = expression;
+ combiner_fullType = fullType;
+ combiner_typeC = typeC;
+ combiner_declaration = declaration;
+ combiner_initialiser = initialiser;
+ combiner_parameter = parameterTypeDef;
+ combiner_parameter_list = parameter_dots;
+ combiner_rule_elem = rule_elem;
+ combiner_statement = statement;
+ combiner_case_line = case_line;
+ combiner_top_level = top_level;
+ combiner_anything = anything;
+ combiner_expression_dots = expression_dots;
+ combiner_statement_dots = statement_dots;
+ combiner_declaration_dots = declaration_dots} in
+ all_functions
+
+(* ---------------------------------------------------------------------- *)
+
+type 'a inout = 'a -> 'a (* for specifying the type of rebuilder *)
+
+type rebuilder =
+ {rebuilder_ident : Ast.ident inout;
+ rebuilder_expression : Ast.expression inout;
+ rebuilder_fullType : Ast.fullType inout;
+ rebuilder_typeC : Ast.typeC inout;
+ rebuilder_declaration : Ast.declaration inout;
+ rebuilder_initialiser : Ast.initialiser inout;
+ rebuilder_parameter : Ast.parameterTypeDef inout;
+ rebuilder_parameter_list : Ast.parameter_list inout;
+ rebuilder_statement : Ast.statement inout;
+ rebuilder_case_line : Ast.case_line inout;
+ rebuilder_rule_elem : Ast.rule_elem inout;
+ rebuilder_top_level : Ast.top_level inout;
+ rebuilder_expression_dots : Ast.expression Ast.dots inout;
+ rebuilder_statement_dots : Ast.statement Ast.dots inout;
+ rebuilder_declaration_dots : Ast.declaration Ast.dots inout;
+ rebuilder_define_param_dots : Ast.define_param Ast.dots inout;
+ rebuilder_define_param : Ast.define_param inout;
+ rebuilder_define_parameters : Ast.define_parameters inout;
+ rebuilder_anything : Ast.anything inout}
+
+type 'mc rmcode = 'mc Ast.mcode inout
+type 'cd rcode = rebuilder -> ('cd inout) -> 'cd inout
+
+
+let rebuilder
+ meta_mcode string_mcode const_mcode assign_mcode fix_mcode unary_mcode
+ binary_mcode cv_mcode base_mcode sign_mcode struct_mcode storage_mcode
+ inc_file_mcode
+ expdotsfn paramdotsfn stmtdotsfn decldotsfn
+ identfn exprfn ftfn tyfn initfn paramfn declfn rulefn stmtfn casefn
+ topfn anyfn =
+ let get_option f = function
+ Some x -> Some (f x)
+ | None -> None in
+ let rec expression_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map expression l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map expression l)
+ | Ast.STARS(l) -> Ast.STARS(List.map expression l)) in
+ expdotsfn all_functions k d
+
+ and parameter_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map parameterTypeDef l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map parameterTypeDef l)
+ | Ast.STARS(l) -> Ast.STARS(List.map parameterTypeDef l)) in
+ paramdotsfn all_functions k d
+
+ and statement_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map statement l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map statement l)
+ | Ast.STARS(l) -> Ast.STARS(List.map statement l)) in
+ stmtdotsfn all_functions k d
+
+ and declaration_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map declaration l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map declaration l)
+ | Ast.STARS(l) -> Ast.STARS(List.map declaration l)) in
+ decldotsfn all_functions k d
+
+ and ident i =
+ let k i =
+ Ast.rewrap i
+ (match Ast.unwrap i with
+ Ast.Id(name) -> Ast.Id(string_mcode name)
+ | Ast.MetaId(name,constraints,keep,inherited) ->
+ Ast.MetaId(meta_mcode name,constraints,keep,inherited)
+ | Ast.MetaFunc(name,constraints,keep,inherited) ->
+ Ast.MetaFunc(meta_mcode name,constraints,keep,inherited)
+ | Ast.MetaLocalFunc(name,constraints,keep,inherited) ->
+ Ast.MetaLocalFunc(meta_mcode name,constraints,keep,inherited)
+ | Ast.OptIdent(id) -> Ast.OptIdent(ident id)
+ | Ast.UniqueIdent(id) -> Ast.UniqueIdent(ident id)) in
+ identfn all_functions k i
+
+ and expression e =
+ let k e =
+ Ast.rewrap e
+ (match Ast.unwrap e with
+ Ast.Ident(id) -> Ast.Ident(ident id)
+ | Ast.Constant(const) -> Ast.Constant(const_mcode const)
+ | Ast.FunCall(fn,lp,args,rp) ->
+ Ast.FunCall(expression fn, string_mcode lp, expression_dots args,
+ string_mcode rp)
+ | Ast.Assignment(left,op,right,simple) ->
+ Ast.Assignment(expression left, assign_mcode op, expression right,
+ simple)
+ | Ast.CondExpr(exp1,why,exp2,colon,exp3) ->
+ Ast.CondExpr(expression exp1, string_mcode why,
+ get_option expression exp2, string_mcode colon,
+ expression exp3)
+ | Ast.Postfix(exp,op) -> Ast.Postfix(expression exp,fix_mcode op)
+ | Ast.Infix(exp,op) -> Ast.Infix(expression exp,fix_mcode op)
+ | Ast.Unary(exp,op) -> Ast.Unary(expression exp,unary_mcode op)
+ | Ast.Binary(left,op,right) ->
+ Ast.Binary(expression left, binary_mcode op, expression right)
+ | Ast.Nested(left,op,right) ->
+ Ast.Nested(expression left, binary_mcode op, expression right)
+ | Ast.Paren(lp,exp,rp) ->
+ Ast.Paren(string_mcode lp, expression exp, string_mcode rp)
+ | Ast.ArrayAccess(exp1,lb,exp2,rb) ->
+ Ast.ArrayAccess(expression exp1, string_mcode lb, expression exp2,
+ string_mcode rb)
+ | Ast.RecordAccess(exp,pt,field) ->
+ Ast.RecordAccess(expression exp, string_mcode pt, ident field)
+ | Ast.RecordPtAccess(exp,ar,field) ->
+ Ast.RecordPtAccess(expression exp, string_mcode ar, ident field)
+ | Ast.Cast(lp,ty,rp,exp) ->
+ Ast.Cast(string_mcode lp, fullType ty, string_mcode rp,
+ expression exp)
+ | Ast.SizeOfExpr(szf,exp) ->
+ Ast.SizeOfExpr(string_mcode szf, expression exp)
+ | Ast.SizeOfType(szf,lp,ty,rp) ->
+ Ast.SizeOfType(string_mcode szf,string_mcode lp, fullType ty,
+ string_mcode rp)
+ | Ast.TypeExp(ty) -> Ast.TypeExp(fullType ty)
+ | Ast.MetaErr(name,constraints,keep,inherited) ->
+ Ast.MetaErr(meta_mcode name,constraints,keep,inherited)
+ | Ast.MetaExpr(name,constraints,keep,ty,form,inherited) ->
+ Ast.MetaExpr(meta_mcode name,constraints,keep,ty,form,inherited)
+ | Ast.MetaExprList(name,lenname_inh,keep,inherited) ->
+ Ast.MetaExprList(meta_mcode name,lenname_inh,keep,inherited)
+ | Ast.EComma(cm) -> Ast.EComma(string_mcode cm)
+ | Ast.DisjExpr(exp_list) -> Ast.DisjExpr(List.map expression exp_list)
+ | Ast.NestExpr(expr_dots,whencode,multi) ->
+ Ast.NestExpr(expression_dots expr_dots,
+ get_option expression whencode,multi)
+ | Ast.Edots(dots,whencode) ->
+ Ast.Edots(string_mcode dots,get_option expression whencode)
+ | Ast.Ecircles(dots,whencode) ->
+ Ast.Ecircles(string_mcode dots,get_option expression whencode)
+ | Ast.Estars(dots,whencode) ->
+ Ast.Estars(string_mcode dots,get_option expression whencode)
+ | Ast.OptExp(exp) -> Ast.OptExp(expression exp)
+ | Ast.UniqueExp(exp) -> Ast.UniqueExp(expression exp)) in
+ exprfn all_functions k e
+
+ and fullType ft =
+ let k ft =
+ Ast.rewrap ft
+ (match Ast.unwrap ft with
+ Ast.Type(cv,ty) -> Ast.Type (get_option cv_mcode cv, typeC ty)
+ | Ast.DisjType(types) -> Ast.DisjType(List.map fullType types)
+ | Ast.OptType(ty) -> Ast.OptType(fullType ty)
+ | Ast.UniqueType(ty) -> Ast.UniqueType(fullType ty)) in
+ ftfn all_functions k ft
+
+ and typeC ty =
+ let k ty =
+ Ast.rewrap ty
+ (match Ast.unwrap ty with
+ Ast.BaseType(ty,sgn) ->
+ Ast.BaseType (base_mcode ty,get_option sign_mcode sgn)
+ | Ast.ImplicitInt(sgn) -> Ast.ImplicitInt (sign_mcode sgn)
+ | Ast.Pointer(ty,star) ->
+ Ast.Pointer (fullType ty, string_mcode star)
+ | Ast.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ Ast.FunctionPointer(fullType ty,string_mcode lp1,string_mcode star,
+ string_mcode rp1,string_mcode lp2,
+ parameter_dots params,
+ string_mcode rp2)
+ | Ast.FunctionType(allminus,ty,lp,params,rp) ->
+ Ast.FunctionType(allminus,get_option fullType ty,string_mcode lp,
+ parameter_dots params,string_mcode rp)
+ | Ast.Array(ty,lb,size,rb) ->
+ Ast.Array(fullType ty, string_mcode lb,
+ get_option expression size, string_mcode rb)
+ | Ast.StructUnionName(kind,name) ->
+ Ast.StructUnionName (struct_mcode kind, get_option ident name)
+ | Ast.StructUnionDef(ty,lb,decls,rb) ->
+ Ast.StructUnionDef (fullType ty,
+ string_mcode lb, declaration_dots decls,
+ string_mcode rb)
+ | Ast.TypeName(name) -> Ast.TypeName(string_mcode name)
+ | Ast.MetaType(name,keep,inherited) ->
+ Ast.MetaType(meta_mcode name,keep,inherited)) in
+ tyfn all_functions k ty
+
+ and declaration d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.Init(stg,ty,id,eq,ini,sem) ->
+ Ast.Init(get_option storage_mcode stg, fullType ty, ident id,
+ string_mcode eq, initialiser ini, string_mcode sem)
+ | Ast.UnInit(stg,ty,id,sem) ->
+ Ast.UnInit(get_option storage_mcode stg, fullType ty, ident id,
+ string_mcode sem)
+ | Ast.MacroDecl(name,lp,args,rp,sem) ->
+ Ast.MacroDecl(ident name, string_mcode lp, expression_dots args,
+ string_mcode rp,string_mcode sem)
+ | Ast.TyDecl(ty,sem) -> Ast.TyDecl(fullType ty, string_mcode sem)
+ | Ast.Typedef(stg,ty,id,sem) ->
+ Ast.Typedef(string_mcode stg, fullType ty, typeC id,
+ string_mcode sem)
+ | Ast.DisjDecl(decls) -> Ast.DisjDecl(List.map declaration decls)
+ | Ast.Ddots(dots,whencode) ->
+ Ast.Ddots(string_mcode dots, get_option declaration whencode)
+ | Ast.MetaDecl(name,keep,inherited) ->
+ Ast.MetaDecl(meta_mcode name,keep,inherited)
+ | Ast.OptDecl(decl) -> Ast.OptDecl(declaration decl)
+ | Ast.UniqueDecl(decl) -> Ast.UniqueDecl(declaration decl)) in
+ declfn all_functions k d
+
+ and initialiser i =
+ let k i =
+ Ast.rewrap i
+ (match Ast.unwrap i with
+ Ast.InitExpr(exp) -> Ast.InitExpr(expression exp)
+ | Ast.InitList(lb,initlist,rb,whencode) ->
+ Ast.InitList(string_mcode lb, List.map initialiser initlist,
+ string_mcode rb, List.map initialiser whencode)
+ | Ast.InitGccDotName(dot,name,eq,ini) ->
+ Ast.InitGccDotName
+ (string_mcode dot, ident name, string_mcode eq, initialiser ini)
+ | Ast.InitGccName(name,eq,ini) ->
+ Ast.InitGccName(ident name, string_mcode eq, initialiser ini)
+ | Ast.InitGccIndex(lb,exp,rb,eq,ini) ->
+ Ast.InitGccIndex
+ (string_mcode lb, expression exp, string_mcode rb,
+ string_mcode eq, initialiser ini)
+ | Ast.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ Ast.InitGccRange
+ (string_mcode lb, expression exp1, string_mcode dots,
+ expression exp2, string_mcode rb, string_mcode eq,
+ initialiser ini)
+ | Ast.IComma(cm) -> Ast.IComma(string_mcode cm)
+ | Ast.OptIni(i) -> Ast.OptIni(initialiser i)
+ | Ast.UniqueIni(i) -> Ast.UniqueIni(initialiser i)) in
+ initfn all_functions k i
+
+ and parameterTypeDef p =
+ let k p =
+ Ast.rewrap p
+ (match Ast.unwrap p with
+ Ast.VoidParam(ty) -> Ast.VoidParam(fullType ty)
+ | Ast.Param(ty,id) -> Ast.Param(fullType ty, get_option ident id)
+ | Ast.MetaParam(name,keep,inherited) ->
+ Ast.MetaParam(meta_mcode name,keep,inherited)
+ | Ast.MetaParamList(name,lenname_inh,keep,inherited) ->
+ Ast.MetaParamList(meta_mcode name,lenname_inh,keep,inherited)
+ | Ast.PComma(cm) -> Ast.PComma(string_mcode cm)
+ | Ast.Pdots(dots) -> Ast.Pdots(string_mcode dots)
+ | Ast.Pcircles(dots) -> Ast.Pcircles(string_mcode dots)
+ | Ast.OptParam(param) -> Ast.OptParam(parameterTypeDef param)
+ | Ast.UniqueParam(param) -> Ast.UniqueParam(parameterTypeDef param)) in
+ paramfn all_functions k p
+
+ and rule_elem re =
+ let k re =
+ Ast.rewrap re
+ (match Ast.unwrap re with
+ Ast.FunHeader(bef,allminus,fi,name,lp,params,rp) ->
+ Ast.FunHeader(bef,allminus,List.map fninfo fi,ident name,
+ string_mcode lp, parameter_dots params,
+ string_mcode rp)
+ | Ast.Decl(bef,allminus,decl) ->
+ Ast.Decl(bef,allminus,declaration decl)
+ | Ast.SeqStart(brace) -> Ast.SeqStart(string_mcode brace)
+ | Ast.SeqEnd(brace) -> Ast.SeqEnd(string_mcode brace)
+ | Ast.ExprStatement(exp,sem) ->
+ Ast.ExprStatement (expression exp, string_mcode sem)
+ | Ast.IfHeader(iff,lp,exp,rp) ->
+ Ast.IfHeader(string_mcode iff, string_mcode lp, expression exp,
+ string_mcode rp)
+ | Ast.Else(els) -> Ast.Else(string_mcode els)
+ | Ast.WhileHeader(whl,lp,exp,rp) ->
+ Ast.WhileHeader(string_mcode whl, string_mcode lp, expression exp,
+ string_mcode rp)
+ | Ast.DoHeader(d) -> Ast.DoHeader(string_mcode d)
+ | Ast.WhileTail(whl,lp,exp,rp,sem) ->
+ Ast.WhileTail(string_mcode whl, string_mcode lp, expression exp,
+ string_mcode rp, string_mcode sem)
+ | Ast.ForHeader(fr,lp,e1,sem1,e2,sem2,e3,rp) ->
+ Ast.ForHeader(string_mcode fr, string_mcode lp,
+ get_option expression e1, string_mcode sem1,
+ get_option expression e2, string_mcode sem2,
+ get_option expression e3, string_mcode rp)
+ | Ast.IteratorHeader(whl,lp,args,rp) ->
+ Ast.IteratorHeader(ident whl, string_mcode lp,
+ expression_dots args, string_mcode rp)
+ | Ast.SwitchHeader(switch,lp,exp,rp) ->
+ Ast.SwitchHeader(string_mcode switch, string_mcode lp,
+ expression exp, string_mcode rp)
+ | Ast.Break(br,sem) ->
+ Ast.Break(string_mcode br, string_mcode sem)
+ | Ast.Continue(cont,sem) ->
+ Ast.Continue(string_mcode cont, string_mcode sem)
+ | Ast.Label(l,dd) -> Ast.Label(ident l, string_mcode dd)
+ | Ast.Goto(goto,l,sem) ->
+ Ast.Goto(string_mcode goto,ident l,string_mcode sem)
+ | Ast.Return(ret,sem) ->
+ Ast.Return(string_mcode ret, string_mcode sem)
+ | Ast.ReturnExpr(ret,exp,sem) ->
+ Ast.ReturnExpr(string_mcode ret, expression exp, string_mcode sem)
+ | Ast.MetaStmt(name,keep,seqible,inherited) ->
+ Ast.MetaStmt(meta_mcode name,keep,seqible,inherited)
+ | Ast.MetaStmtList(name,keep,inherited) ->
+ Ast.MetaStmtList(meta_mcode name,keep,inherited)
+ | Ast.MetaRuleElem(name,keep,inherited) ->
+ Ast.MetaRuleElem(meta_mcode name,keep,inherited)
+ | Ast.Exp(exp) -> Ast.Exp(expression exp)
+ | Ast.TopExp(exp) -> Ast.TopExp(expression exp)
+ | Ast.Ty(ty) -> Ast.Ty(fullType ty)
+ | Ast.Include(inc,name) ->
+ Ast.Include(string_mcode inc,inc_file_mcode name)
+ | Ast.DefineHeader(def,id,params) ->
+ Ast.DefineHeader(string_mcode def,ident id,
+ define_parameters params)
+ | Ast.Default(def,colon) ->
+ Ast.Default(string_mcode def,string_mcode colon)
+ | Ast.Case(case,exp,colon) ->
+ Ast.Case(string_mcode case,expression exp,string_mcode colon)
+ | Ast.DisjRuleElem(res) -> Ast.DisjRuleElem(List.map rule_elem res)) in
+ rulefn all_functions k re
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ Ast.rewrap p
+ (match Ast.unwrap p with
+ Ast.NoParams -> Ast.NoParams
+ | Ast.DParams(lp,params,rp) ->
+ Ast.DParams(string_mcode lp,define_param_dots params,
+ string_mcode rp)) in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ Ast.rewrap d
+ (match Ast.unwrap d with
+ Ast.DOTS(l) -> Ast.DOTS(List.map define_param l)
+ | Ast.CIRCLES(l) -> Ast.CIRCLES(List.map define_param l)
+ | Ast.STARS(l) -> Ast.STARS(List.map define_param l)) in
+ k d
+
+ and define_param p =
+ let k p =
+ Ast.rewrap p
+ (match Ast.unwrap p with
+ Ast.DParam(id) -> Ast.DParam(ident id)
+ | Ast.DPComma(comma) -> Ast.DPComma(string_mcode comma)
+ | Ast.DPdots(d) -> Ast.DPdots(string_mcode d)
+ | Ast.DPcircles(c) -> Ast.DPcircles(string_mcode c)
+ | Ast.OptDParam(dp) -> Ast.OptDParam(define_param dp)
+ | Ast.UniqueDParam(dp) -> Ast.UniqueDParam(define_param dp)) in
+ k p
+
+ and process_bef_aft s =
+ Ast.set_dots_bef_aft
+ (match Ast.get_dots_bef_aft s with
+ Ast.NoDots -> Ast.NoDots
+ | Ast.DroppingBetweenDots(stm,ind) ->
+ Ast.DroppingBetweenDots(statement stm,ind)
+ | Ast.AddingBetweenDots(stm,ind) ->
+ Ast.AddingBetweenDots(statement stm,ind))
+ s
+
+ and statement s =
+ let k s =
+ Ast.rewrap s
+ (match Ast.unwrap s with
+ Ast.Seq(lbrace,decls,body,rbrace) ->
+ Ast.Seq(rule_elem lbrace, statement_dots decls,
+ statement_dots body, rule_elem rbrace)
+ | Ast.IfThen(header,branch,aft) ->
+ Ast.IfThen(rule_elem header, statement branch,aft)
+ | Ast.IfThenElse(header,branch1,els,branch2,aft) ->
+ Ast.IfThenElse(rule_elem header, statement branch1, rule_elem els,
+ statement branch2, aft)
+ | Ast.While(header,body,aft) ->
+ Ast.While(rule_elem header, statement body, aft)
+ | Ast.Do(header,body,tail) ->
+ Ast.Do(rule_elem header, statement body, rule_elem tail)
+ | Ast.For(header,body,aft) ->
+ Ast.For(rule_elem header, statement body, aft)
+ | Ast.Iterator(header,body,aft) ->
+ Ast.Iterator(rule_elem header, statement body, aft)
+ | Ast.Switch(header,lb,cases,rb) ->
+ Ast.Switch(rule_elem header,rule_elem lb,
+ List.map case_line cases,rule_elem rb)
+ | Ast.Atomic(re) -> Ast.Atomic(rule_elem re)
+ | Ast.Disj(stmt_dots_list) ->
+ Ast.Disj (List.map statement_dots stmt_dots_list)
+ | Ast.Nest(stmt_dots,whn,multi,bef,aft) ->
+ Ast.Nest(statement_dots stmt_dots,
+ List.map (whencode statement_dots statement) whn,
+ multi,bef,aft)
+ | Ast.FunDecl(header,lbrace,decls,body,rbrace) ->
+ Ast.FunDecl(rule_elem header,rule_elem lbrace,
+ statement_dots decls,
+ statement_dots body, rule_elem rbrace)
+ | Ast.Define(header,body) ->
+ Ast.Define(rule_elem header,statement_dots body)
+ | Ast.Dots(d,whn,bef,aft) ->
+ Ast.Dots(string_mcode d,
+ List.map (whencode statement_dots statement) whn,bef,aft)
+ | Ast.Circles(d,whn,bef,aft) ->
+ Ast.Circles(string_mcode d,
+ List.map (whencode statement_dots statement) whn,
+ bef,aft)
+ | Ast.Stars(d,whn,bef,aft) ->
+ Ast.Stars(string_mcode d,
+ List.map (whencode statement_dots statement) whn,bef,aft)
+ | Ast.OptStm(stmt) -> Ast.OptStm(statement stmt)
+ | Ast.UniqueStm(stmt) -> Ast.UniqueStm(statement stmt)) in
+ let s = stmtfn all_functions k s in
+ (* better to do this after, in case there is an equality test on the whole
+ statement, eg in free_vars. equality test would require that this
+ subterm not already be changed *)
+ process_bef_aft s
+
+ and fninfo = function
+ Ast.FStorage(stg) -> Ast.FStorage(storage_mcode stg)
+ | Ast.FType(ty) -> Ast.FType(fullType ty)
+ | Ast.FInline(inline) -> Ast.FInline(string_mcode inline)
+ | Ast.FAttr(attr) -> Ast.FAttr(string_mcode attr)
+
+ and whencode notfn alwaysfn = function
+ Ast.WhenNot a -> Ast.WhenNot (notfn a)
+ | Ast.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
+ | Ast.WhenModifier(x) -> Ast.WhenModifier(x)
+ | Ast.WhenNotTrue(e) -> Ast.WhenNotTrue(rule_elem e)
+ | Ast.WhenNotFalse(e) -> Ast.WhenNotFalse(rule_elem e)
+
+ and case_line c =
+ let k c =
+ Ast.rewrap c
+ (match Ast.unwrap c with
+ Ast.CaseLine(header,code) ->
+ Ast.CaseLine(rule_elem header,statement_dots code)
+ | Ast.OptCase(case) -> Ast.OptCase(case_line case)) in
+ casefn all_functions k c
+
+ and top_level t =
+ let k t =
+ Ast.rewrap t
+ (match Ast.unwrap t with
+ Ast.FILEINFO(old_file,new_file) ->
+ Ast.FILEINFO (string_mcode old_file, string_mcode new_file)
+ | Ast.DECL(stmt) -> Ast.DECL(statement stmt)
+ | Ast.CODE(stmt_dots) -> Ast.CODE(statement_dots stmt_dots)
+ | Ast.ERRORWORDS(exps) -> Ast.ERRORWORDS (List.map expression exps)) in
+ topfn all_functions k t
+
+ and anything a =
+ let k = function
+ (*in many cases below, the thing is not even mcode, so we do nothing*)
+ Ast.FullTypeTag(ft) -> Ast.FullTypeTag(fullType ft)
+ | Ast.BaseTypeTag(bt) as x -> x
+ | Ast.StructUnionTag(su) as x -> x
+ | Ast.SignTag(sgn) as x -> x
+ | Ast.IdentTag(id) -> Ast.IdentTag(ident id)
+ | Ast.ExpressionTag(exp) -> Ast.ExpressionTag(expression exp)
+ | Ast.ConstantTag(cst) as x -> x
+ | Ast.UnaryOpTag(unop) as x -> x
+ | Ast.AssignOpTag(asgnop) as x -> x
+ | Ast.FixOpTag(fixop) as x -> x
+ | Ast.BinaryOpTag(binop) as x -> x
+ | Ast.ArithOpTag(arithop) as x -> x
+ | Ast.LogicalOpTag(logop) as x -> x
+ | Ast.InitTag(decl) -> Ast.InitTag(initialiser decl)
+ | Ast.DeclarationTag(decl) -> Ast.DeclarationTag(declaration decl)
+ | Ast.StorageTag(stg) as x -> x
+ | Ast.IncFileTag(stg) as x -> x
+ | Ast.Rule_elemTag(rule) -> Ast.Rule_elemTag(rule_elem rule)
+ | Ast.StatementTag(rule) -> Ast.StatementTag(statement rule)
+ | Ast.CaseLineTag(case) -> Ast.CaseLineTag(case_line case)
+ | Ast.ConstVolTag(cv) as x -> x
+ | Ast.Token(tok,info) as x -> x
+ | Ast.Code(cd) -> Ast.Code(top_level cd)
+ | Ast.ExprDotsTag(ed) -> Ast.ExprDotsTag(expression_dots ed)
+ | Ast.ParamDotsTag(pd) -> Ast.ParamDotsTag(parameter_dots pd)
+ | Ast.StmtDotsTag(sd) -> Ast.StmtDotsTag(statement_dots sd)
+ | Ast.DeclDotsTag(sd) -> Ast.DeclDotsTag(declaration_dots sd)
+ | Ast.TypeCTag(ty) -> Ast.TypeCTag(typeC ty)
+ | Ast.ParamTag(param) -> Ast.ParamTag(parameterTypeDef param)
+ | Ast.SgrepStartTag(tok) as x -> x
+ | Ast.SgrepEndTag(tok) as x -> x in
+ anyfn all_functions k a
+
+ and all_functions =
+ {rebuilder_ident = ident;
+ rebuilder_expression = expression;
+ rebuilder_fullType= fullType;
+ rebuilder_typeC = typeC;
+ rebuilder_declaration = declaration;
+ rebuilder_initialiser = initialiser;
+ rebuilder_parameter = parameterTypeDef;
+ rebuilder_parameter_list = parameter_dots;
+ rebuilder_rule_elem = rule_elem;
+ rebuilder_statement = statement;
+ rebuilder_case_line = case_line;
+ rebuilder_top_level = top_level;
+ rebuilder_expression_dots = expression_dots;
+ rebuilder_statement_dots = statement_dots;
+ rebuilder_declaration_dots = declaration_dots;
+ rebuilder_define_param_dots = define_param_dots;
+ rebuilder_define_param = define_param;
+ rebuilder_define_parameters = define_parameters;
+ rebuilder_anything = anything} in
+ all_functions
+
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+
+(* --------------------------------------------------------------------- *)
+(* Generic traversal: combiner *)
+(* parameters:
+ combining function
+ treatment of: mcode, identifiers, expressions, typeCs, types,
+ declarations, statements, toplevels
+ default value for options *)
+
+type 'a combiner =
+ {combiner_ident : Ast0.ident -> 'a;
+ combiner_expression : Ast0.expression -> 'a;
+ combiner_typeC : Ast0.typeC -> 'a;
+ combiner_declaration : Ast0.declaration -> 'a;
+ combiner_initialiser : Ast0.initialiser -> 'a;
+ combiner_initialiser_list : Ast0.initialiser_list -> 'a;
+ combiner_parameter : Ast0.parameterTypeDef -> 'a;
+ combiner_parameter_list : Ast0.parameter_list -> 'a;
+ combiner_statement : Ast0.statement -> 'a;
+ combiner_case_line : Ast0.case_line -> 'a;
+ combiner_top_level : Ast0.top_level -> 'a;
+ combiner_expression_dots :
+ Ast0.expression Ast0.dots -> 'a;
+ combiner_statement_dots :
+ Ast0.statement Ast0.dots -> 'a;
+ combiner_declaration_dots :
+ Ast0.declaration Ast0.dots -> 'a;
+ combiner_case_line_dots :
+ Ast0.case_line Ast0.dots -> 'a;
+ combiner_anything : Ast0.anything -> 'a}
+
+
+type ('mc,'a) cmcode = 'mc Ast0.mcode -> 'a
+type ('cd,'a) ccode = 'a combiner -> ('cd -> 'a) -> 'cd -> 'a
+
+let combiner bind option_default
+ meta_mcode string_mcode const_mcode assign_mcode fix_mcode unary_mcode
+ binary_mcode cv_mcode base_mcode sign_mcode struct_mcode storage_mcode
+ inc_mcode
+ dotsexprfn dotsinitfn dotsparamfn dotsstmtfn dotsdeclfn dotscasefn
+ identfn exprfn
+ tyfn initfn paramfn declfn stmtfn casefn topfn =
+ let multibind l =
+ let rec loop = function
+ [] -> option_default
+ | [x] -> x
+ | x::xs -> bind x (loop xs) in
+ loop l in
+ let get_option f = function
+ Some x -> f x
+ | None -> option_default in
+ let rec expression_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map expression l) in
+ dotsexprfn all_functions k d
+ and initialiser_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map initialiser l) in
+ dotsinitfn all_functions k d
+ and parameter_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map parameterTypeDef l) in
+ dotsparamfn all_functions k d
+ and statement_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map statement l) in
+ dotsstmtfn all_functions k d
+ and declaration_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map declaration l) in
+ dotsdeclfn all_functions k d
+ and case_line_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map case_line l) in
+ dotscasefn all_functions k d
+ and ident i =
+ let k i =
+ match Ast0.unwrap i with
+ Ast0.Id(name) -> string_mcode name
+ | Ast0.MetaId(name,_,_) -> meta_mcode name
+ | Ast0.MetaFunc(name,_,_) -> meta_mcode name
+ | Ast0.MetaLocalFunc(name,_,_) -> meta_mcode name
+ | Ast0.OptIdent(id) -> ident id
+ | Ast0.UniqueIdent(id) -> ident id in
+ identfn all_functions k i
+ and expression e =
+ let k e =
+ match Ast0.unwrap e with
+ Ast0.Ident(id) -> ident id
+ | Ast0.Constant(const) -> const_mcode const
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ multibind
+ [expression fn; string_mcode lp; expression_dots args;
+ string_mcode rp]
+ | Ast0.Assignment(left,op,right,_) ->
+ multibind [expression left; assign_mcode op; expression right]
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ multibind
+ [expression exp1; string_mcode why; get_option expression exp2;
+ string_mcode colon; expression exp3]
+ | Ast0.Postfix(exp,op) -> bind (expression exp) (fix_mcode op)
+ | Ast0.Infix(exp,op) -> bind (fix_mcode op) (expression exp)
+ | Ast0.Unary(exp,op) -> bind (unary_mcode op) (expression exp)
+ | Ast0.Binary(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast0.Nested(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast0.Paren(lp,exp,rp) ->
+ multibind [string_mcode lp; expression exp; string_mcode rp]
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ multibind
+ [expression exp1; string_mcode lb; expression exp2;
+ string_mcode rb]
+ | Ast0.RecordAccess(exp,pt,field) ->
+ multibind [expression exp; string_mcode pt; ident field]
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ multibind [expression exp; string_mcode ar; ident field]
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ multibind
+ [string_mcode lp; typeC ty; string_mcode rp; expression exp]
+ | Ast0.SizeOfExpr(szf,exp) ->
+ multibind [string_mcode szf; expression exp]
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ multibind
+ [string_mcode szf; string_mcode lp; typeC ty; string_mcode rp]
+ | Ast0.TypeExp(ty) -> typeC ty
+ | Ast0.MetaErr(name,_,_)
+ | Ast0.MetaExpr(name,_,_,_,_)
+ | Ast0.MetaExprList(name,_,_) -> meta_mcode name
+ | Ast0.EComma(cm) -> string_mcode cm
+ | Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ (match expr_list with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (expression x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (expression x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ bind (string_mcode starter)
+ (bind (expression_dots expr_dots)
+ (bind (string_mcode ender) (get_option expression whencode)))
+ | Ast0.Edots(dots,whencode) | Ast0.Ecircles(dots,whencode)
+ | Ast0.Estars(dots,whencode) ->
+ bind (string_mcode dots) (get_option expression whencode)
+ | Ast0.OptExp(exp) -> expression exp
+ | Ast0.UniqueExp(exp) -> expression exp in
+ exprfn all_functions k e
+ and function_pointer (ty,lp1,star,rp1,lp2,params,rp2) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind
+ ([typeC ty; string_mcode lp1; string_mcode star] @ extra @
+ [string_mcode rp1;
+ string_mcode lp2; parameter_dots params; string_mcode rp2])
+ and function_type (ty,lp1,params,rp1) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind ([get_option typeC ty] @ extra @
+ [string_mcode lp1; parameter_dots params; string_mcode rp1])
+ and array_type (ty,lb,size,rb) extra =
+ multibind
+ ([typeC ty] @ extra @
+ [string_mcode lb; get_option expression size; string_mcode rb])
+ and typeC t =
+ let k t =
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> bind (cv_mcode cv) (typeC ty)
+ | Ast0.BaseType(ty,sign) ->
+ bind (get_option sign_mcode sign) (base_mcode ty)
+ | Ast0.ImplicitInt(sign) -> (sign_mcode sign)
+ | Ast0.Pointer(ty,star) -> bind (typeC ty) (string_mcode star)
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) []
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) []
+ | Ast0.Array(ty,lb,size,rb) ->
+ array_type (ty,lb,size,rb) []
+ | Ast0.StructUnionName(kind,name) ->
+ bind (struct_mcode kind) (get_option ident name)
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ multibind
+ [typeC ty;string_mcode lb;declaration_dots decls;string_mcode rb]
+ | Ast0.TypeName(name) -> string_mcode name
+ | Ast0.MetaType(name,_) -> meta_mcode name
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ (match types with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (typeC x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (typeC x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.OptType(ty) -> typeC ty
+ | Ast0.UniqueType(ty) -> typeC ty in
+ tyfn all_functions k t
+ and named_type ty id =
+ match Ast0.unwrap ty with
+ Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) [ident id]
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) [ident id]
+ | Ast0.Array(ty,lb,size,rb) ->
+ array_type (ty,lb,size,rb) [ident id]
+ | _ -> bind (typeC ty) (ident id)
+ and declaration d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id)
+ (multibind
+ [string_mcode eq; initialiser ini; string_mcode sem]))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id) (string_mcode sem))
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ multibind
+ [ident name; string_mcode lp; expression_dots args;
+ string_mcode rp; string_mcode sem]
+ | Ast0.TyDecl(ty,sem) -> bind (typeC ty) (string_mcode sem)
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ bind (string_mcode stg)
+ (bind (typeC ty) (bind (typeC id) (string_mcode sem)))
+ | Ast0.DisjDecl(starter,decls,mids,ender) ->
+ (match decls with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (declaration x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (declaration x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.Ddots(dots,whencode) ->
+ bind (string_mcode dots) (get_option declaration whencode)
+ | Ast0.OptDecl(decl) -> declaration decl
+ | Ast0.UniqueDecl(decl) -> declaration decl in
+ declfn all_functions k d
+ and initialiser i =
+ let k i =
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> expression exp
+ | Ast0.InitList(lb,initlist,rb) ->
+ multibind
+ [string_mcode lb; initialiser_dots initlist; string_mcode rb]
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ multibind
+ [string_mcode dot; ident name; string_mcode eq; initialiser ini]
+ | Ast0.InitGccName(name,eq,ini) ->
+ multibind [ident name; string_mcode eq; initialiser ini]
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp; string_mcode rb;
+ string_mcode eq; initialiser ini]
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp1; string_mcode dots;
+ expression exp2; string_mcode rb; string_mcode eq;
+ initialiser ini]
+ | Ast0.IComma(cm) -> string_mcode cm
+ | Ast0.Idots(dots,whencode) ->
+ bind (string_mcode dots) (get_option initialiser whencode)
+ | Ast0.OptIni(i) -> initialiser i
+ | Ast0.UniqueIni(i) -> initialiser i in
+ initfn all_functions k i
+ and parameterTypeDef p =
+ let k p =
+ match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> typeC ty
+ | Ast0.Param(ty,Some id) -> named_type ty id
+ | Ast0.Param(ty,None) -> typeC ty
+ | Ast0.MetaParam(name,_) -> meta_mcode name
+ | Ast0.MetaParamList(name,_,_) -> meta_mcode name
+ | Ast0.PComma(cm) -> string_mcode cm
+ | Ast0.Pdots(dots) -> string_mcode dots
+ | Ast0.Pcircles(dots) -> string_mcode dots
+ | Ast0.OptParam(param) -> parameterTypeDef param
+ | Ast0.UniqueParam(param) -> parameterTypeDef param in
+ paramfn all_functions k p
+
+ (* discard the result, because the statement is assumed to be already
+ represented elsewhere in the code *)
+ and process_bef_aft s =
+ match Ast0.get_dots_bef_aft s with
+ Ast0.NoDots -> ()
+ | Ast0.DroppingBetweenDots(stm) -> let _ = statement stm in ()
+ | Ast0.AddingBetweenDots(stm) -> let _ = statement stm in ()
+
+ and statement s =
+ process_bef_aft s;
+ let k s =
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ multibind
+ ((List.map fninfo fi) @
+ [ident name; string_mcode lp;
+ parameter_dots params; string_mcode rp; string_mcode lbrace;
+ statement_dots body; string_mcode rbrace])
+ | Ast0.Decl(_,decl) -> declaration decl
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ multibind
+ [string_mcode lbrace; statement_dots body; string_mcode rbrace]
+ | Ast0.ExprStatement(exp,sem) ->
+ bind (expression exp) (string_mcode sem)
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,_) ->
+ multibind
+ [string_mcode iff; string_mcode lp; expression exp;
+ string_mcode rp; statement branch1]
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,_) ->
+ multibind
+ [string_mcode iff; string_mcode lp; expression exp;
+ string_mcode rp; statement branch1; string_mcode els;
+ statement branch2]
+ | Ast0.While(whl,lp,exp,rp,body,_) ->
+ multibind
+ [string_mcode whl; string_mcode lp; expression exp;
+ string_mcode rp; statement body]
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
+ multibind
+ [string_mcode d; statement body; string_mcode whl;
+ string_mcode lp; expression exp; string_mcode rp;
+ string_mcode sem]
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,_) ->
+ multibind
+ [string_mcode fr; string_mcode lp; get_option expression e1;
+ string_mcode sem1; get_option expression e2; string_mcode sem2;
+ get_option expression e3;
+ string_mcode rp; statement body]
+ | Ast0.Iterator(nm,lp,args,rp,body,_) ->
+ multibind
+ [ident nm; string_mcode lp; expression_dots args;
+ string_mcode rp; statement body]
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ multibind
+ [string_mcode switch; string_mcode lp; expression exp;
+ string_mcode rp; string_mcode lb; case_line_dots cases;
+ string_mcode rb]
+ | Ast0.Break(br,sem) -> bind (string_mcode br) (string_mcode sem)
+ | Ast0.Continue(cont,sem) -> bind (string_mcode cont) (string_mcode sem)
+ | Ast0.Label(l,dd) -> bind (ident l) (string_mcode dd)
+ | Ast0.Goto(goto,l,sem) ->
+ bind (string_mcode goto) (bind (ident l) (string_mcode sem))
+ | Ast0.Return(ret,sem) -> bind (string_mcode ret) (string_mcode sem)
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ multibind [string_mcode ret; expression exp; string_mcode sem]
+ | Ast0.MetaStmt(name,_) -> meta_mcode name
+ | Ast0.MetaStmtList(name,_) -> meta_mcode name
+ | Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ (match statement_dots_list with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (statement_dots x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (statement_dots x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.Nest(starter,stmt_dots,ender,whn,multi) ->
+ bind (string_mcode starter)
+ (bind (statement_dots stmt_dots)
+ (bind (string_mcode ender)
+ (multibind
+ (List.map (whencode statement_dots statement) whn))))
+ | Ast0.Exp(exp) -> expression exp
+ | Ast0.TopExp(exp) -> expression exp
+ | Ast0.Ty(ty) -> typeC ty
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
+ bind (string_mcode d)
+ (multibind (List.map (whencode statement_dots statement) whn))
+ | Ast0.Include(inc,name) -> bind (string_mcode inc) (inc_mcode name)
+ | Ast0.Define(def,id,params,body) ->
+ multibind [string_mcode def; ident id; define_parameters params;
+ statement_dots body]
+ | Ast0.OptStm(re) -> statement re
+ | Ast0.UniqueStm(re) -> statement re in
+ stmtfn all_functions k s
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ match Ast0.unwrap p with
+ Ast0.NoParams -> option_default
+ | Ast0.DParams(lp,params,rp) ->
+ multibind
+ [string_mcode lp; define_param_dots params; string_mcode rp] in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map define_param l) in
+ k d
+
+ and define_param p =
+ let k p =
+ match Ast0.unwrap p with
+ Ast0.DParam(id) -> ident id
+ | Ast0.DPComma(comma) -> string_mcode comma
+ | Ast0.DPdots(d) -> string_mcode d
+ | Ast0.DPcircles(c) -> string_mcode c
+ | Ast0.OptDParam(dp) -> define_param dp
+ | Ast0.UniqueDParam(dp) -> define_param dp in
+ k p
+
+ and fninfo = function
+ Ast0.FStorage(stg) -> storage_mcode stg
+ | Ast0.FType(ty) -> typeC ty
+ | Ast0.FInline(inline) -> string_mcode inline
+ | Ast0.FAttr(init) -> string_mcode init
+
+ and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> notfn a
+ | Ast0.WhenAlways a -> alwaysfn a
+ | Ast0.WhenModifier(_) -> option_default
+
+ and case_line c =
+ let k c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ multibind [string_mcode def;string_mcode colon;statement_dots code]
+ | Ast0.Case(case,exp,colon,code) ->
+ multibind [string_mcode case;expression exp;string_mcode colon;
+ statement_dots code]
+ | Ast0.OptCase(case) -> case_line case in
+ casefn all_functions k c
+
+ and anything a = (* for compile_iso, not parameterisable *)
+ let k = function
+ Ast0.DotsExprTag(exprs) -> expression_dots exprs
+ | Ast0.DotsInitTag(inits) -> initialiser_dots inits
+ | Ast0.DotsParamTag(params) -> parameter_dots params
+ | Ast0.DotsStmtTag(stmts) -> statement_dots stmts
+ | Ast0.DotsDeclTag(decls) -> declaration_dots decls
+ | Ast0.DotsCaseTag(cases) -> case_line_dots cases
+ | Ast0.IdentTag(id) -> ident id
+ | Ast0.ExprTag(exp) -> expression exp
+ | Ast0.ArgExprTag(exp) -> expression exp
+ | Ast0.TestExprTag(exp) -> expression exp
+ | Ast0.TypeCTag(ty) -> typeC ty
+ | Ast0.ParamTag(param) -> parameterTypeDef param
+ | Ast0.InitTag(init) -> initialiser init
+ | Ast0.DeclTag(decl) -> declaration decl
+ | Ast0.StmtTag(stmt) -> statement stmt
+ | Ast0.CaseLineTag(c) -> case_line c
+ | Ast0.TopTag(top) -> top_level top
+ | Ast0.IsoWhenTag(_) -> option_default
+ | Ast0.MetaPosTag(var) -> failwith "not supported" in
+ k a
+
+ and top_level t =
+ let k t =
+ match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ bind (string_mcode old_file) (string_mcode new_file)
+ | Ast0.DECL(stmt_dots) -> statement stmt_dots
+ | Ast0.CODE(stmt_dots) -> statement_dots stmt_dots
+ | Ast0.ERRORWORDS(exps) -> multibind (List.map expression exps)
+ | Ast0.OTHER(_) -> failwith "unexpected code" in
+ topfn all_functions k t
+ and all_functions =
+ {combiner_ident = ident;
+ combiner_expression = expression;
+ combiner_typeC = typeC;
+ combiner_declaration = declaration;
+ combiner_initialiser = initialiser;
+ combiner_initialiser_list = initialiser_dots;
+ combiner_parameter = parameterTypeDef;
+ combiner_parameter_list = parameter_dots;
+ combiner_statement = statement;
+ combiner_case_line = case_line;
+ combiner_top_level = top_level;
+ combiner_expression_dots = expression_dots;
+ combiner_statement_dots = statement_dots;
+ combiner_declaration_dots = declaration_dots;
+ combiner_case_line_dots = case_line_dots;
+ combiner_anything = anything} in
+ all_functions
+
+(* --------------------------------------------------------------------- *)
+(* Generic traversal: rebuilder *)
+
+type 'a inout = 'a -> 'a (* for specifying the type of rebuilder *)
+
+type rebuilder =
+ {rebuilder_ident : Ast0.ident inout;
+ rebuilder_expression : Ast0.expression inout;
+ rebuilder_typeC : Ast0.typeC inout;
+ rebuilder_declaration : Ast0.declaration inout;
+ rebuilder_initialiser : Ast0.initialiser inout;
+ rebuilder_initialiser_list : Ast0.initialiser_list inout;
+ rebuilder_parameter : Ast0.parameterTypeDef inout;
+ rebuilder_parameter_list : Ast0.parameter_list inout;
+ rebuilder_statement : Ast0.statement inout;
+ rebuilder_case_line : Ast0.case_line inout;
+ rebuilder_top_level : Ast0.top_level inout;
+ rebuilder_expression_dots :
+ Ast0.expression Ast0.dots ->
+ Ast0.expression Ast0.dots;
+ rebuilder_statement_dots :
+ Ast0.statement Ast0.dots ->
+ Ast0.statement Ast0.dots;
+ rebuilder_declaration_dots :
+ Ast0.declaration Ast0.dots ->
+ Ast0.declaration Ast0.dots;
+ rebuilder_case_line_dots :
+ Ast0.case_line Ast0.dots ->
+ Ast0.case_line Ast0.dots;
+ rebuilder_anything :
+ Ast0.anything -> Ast0.anything}
+
+type 'mc rmcode = 'mc Ast0.mcode inout
+type 'cd rcode = rebuilder -> ('cd inout) -> 'cd inout
+
+let rebuilder = fun
+ meta_mcode string_mcode const_mcode assign_mcode fix_mcode unary_mcode
+ binary_mcode cv_mcode base_mcode sign_mcode struct_mcode storage_mcode
+ inc_mcode
+ dotsexprfn dotsinitfn dotsparamfn dotsstmtfn dotsdeclfn dotscasefn
+ identfn exprfn tyfn initfn paramfn declfn stmtfn casefn topfn ->
+ let get_option f = function
+ Some x -> Some (f x)
+ | None -> None in
+ let rec expression_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map expression l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map expression l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map expression l)) in
+ dotsexprfn all_functions k d
+ and initialiser_list i =
+ let k i =
+ Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map initialiser l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map initialiser l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map initialiser l)) in
+ dotsinitfn all_functions k i
+ and parameter_list d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map parameterTypeDef l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map parameterTypeDef l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map parameterTypeDef l)) in
+ dotsparamfn all_functions k d
+ and statement_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map statement l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map statement l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map statement l)) in
+ dotsstmtfn all_functions k d
+ and declaration_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map declaration l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map declaration l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map declaration l)) in
+ dotsdeclfn all_functions k d
+ and case_line_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map case_line l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map case_line l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map case_line l)) in
+ dotscasefn all_functions k d
+ and ident i =
+ let k i =
+ Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.Id(name) -> Ast0.Id(string_mcode name)
+ | Ast0.MetaId(name,constraints,pure) ->
+ Ast0.MetaId(meta_mcode name,constraints,pure)
+ | Ast0.MetaFunc(name,constraints,pure) ->
+ Ast0.MetaFunc(meta_mcode name,constraints,pure)
+ | Ast0.MetaLocalFunc(name,constraints,pure) ->
+ Ast0.MetaLocalFunc(meta_mcode name,constraints,pure)
+ | Ast0.OptIdent(id) -> Ast0.OptIdent(ident id)
+ | Ast0.UniqueIdent(id) -> Ast0.UniqueIdent(ident id)) in
+ identfn all_functions k i
+ and expression e =
+ let k e =
+ Ast0.rewrap e
+ (match Ast0.unwrap e with
+ Ast0.Ident(id) -> Ast0.Ident(ident id)
+ | Ast0.Constant(const) -> Ast0.Constant(const_mcode const)
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ Ast0.FunCall(expression fn,string_mcode lp,expression_dots args,
+ string_mcode rp)
+ | Ast0.Assignment(left,op,right,simple) ->
+ Ast0.Assignment(expression left,assign_mcode op,expression right,
+ simple)
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ Ast0.CondExpr(expression exp1, string_mcode why,
+ get_option expression exp2, string_mcode colon,
+ expression exp3)
+ | Ast0.Postfix(exp,op) -> Ast0.Postfix(expression exp, fix_mcode op)
+ | Ast0.Infix(exp,op) -> Ast0.Infix(expression exp, fix_mcode op)
+ | Ast0.Unary(exp,op) -> Ast0.Unary(expression exp, unary_mcode op)
+ | Ast0.Binary(left,op,right) ->
+ Ast0.Binary(expression left, binary_mcode op, expression right)
+ | Ast0.Nested(left,op,right) ->
+ Ast0.Nested(expression left, binary_mcode op, expression right)
+ | Ast0.Paren(lp,exp,rp) ->
+ Ast0.Paren(string_mcode lp, expression exp, string_mcode rp)
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ Ast0.ArrayAccess(expression exp1,string_mcode lb,expression exp2,
+ string_mcode rb)
+ | Ast0.RecordAccess(exp,pt,field) ->
+ Ast0.RecordAccess(expression exp, string_mcode pt, ident field)
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ Ast0.RecordPtAccess(expression exp, string_mcode ar, ident field)
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ Ast0.Cast(string_mcode lp, typeC ty, string_mcode rp,
+ expression exp)
+ | Ast0.SizeOfExpr(szf,exp) ->
+ Ast0.SizeOfExpr(string_mcode szf, expression exp)
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ Ast0.SizeOfType(string_mcode szf,string_mcode lp, typeC ty,
+ string_mcode rp)
+ | Ast0.TypeExp(ty) -> Ast0.TypeExp(typeC ty)
+ | Ast0.MetaErr(name,constraints,pure) ->
+ Ast0.MetaErr(meta_mcode name,constraints,pure)
+ | Ast0.MetaExpr(name,constraints,ty,form,pure) ->
+ Ast0.MetaExpr(meta_mcode name,constraints,ty,form,pure)
+ | Ast0.MetaExprList(name,lenname,pure) ->
+ Ast0.MetaExprList(meta_mcode name,lenname,pure)
+ | Ast0.EComma(cm) -> Ast0.EComma(string_mcode cm)
+ | Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ Ast0.DisjExpr(string_mcode starter,List.map expression expr_list,
+ List.map string_mcode mids,string_mcode ender)
+ | Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ Ast0.NestExpr(string_mcode starter,expression_dots expr_dots,
+ string_mcode ender, get_option expression whencode,
+ multi)
+ | Ast0.Edots(dots,whencode) ->
+ Ast0.Edots(string_mcode dots, get_option expression whencode)
+ | Ast0.Ecircles(dots,whencode) ->
+ Ast0.Ecircles(string_mcode dots, get_option expression whencode)
+ | Ast0.Estars(dots,whencode) ->
+ Ast0.Estars(string_mcode dots, get_option expression whencode)
+ | Ast0.OptExp(exp) -> Ast0.OptExp(expression exp)
+ | Ast0.UniqueExp(exp) -> Ast0.UniqueExp(expression exp)) in
+ exprfn all_functions k e
+ and typeC t =
+ let k t =
+ Ast0.rewrap t
+ (match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> Ast0.ConstVol(cv_mcode cv,typeC ty)
+ | Ast0.BaseType(ty,sign) ->
+ Ast0.BaseType(base_mcode ty, get_option sign_mcode sign)
+ | Ast0.ImplicitInt(sign) -> Ast0.ImplicitInt(sign_mcode sign)
+ | Ast0.Pointer(ty,star) ->
+ Ast0.Pointer(typeC ty, string_mcode star)
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ Ast0.FunctionPointer(typeC ty,string_mcode lp1,string_mcode star,
+ string_mcode rp1,string_mcode lp2,
+ parameter_list params,
+ string_mcode rp2)
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ Ast0.FunctionType(get_option typeC ty,
+ string_mcode lp1,parameter_list params,
+ string_mcode rp1)
+ | Ast0.Array(ty,lb,size,rb) ->
+ Ast0.Array(typeC ty, string_mcode lb,
+ get_option expression size, string_mcode rb)
+ | Ast0.StructUnionName(kind,name) ->
+ Ast0.StructUnionName (struct_mcode kind, get_option ident name)
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ Ast0.StructUnionDef (typeC ty,
+ string_mcode lb, declaration_dots decls,
+ string_mcode rb)
+ | Ast0.TypeName(name) -> Ast0.TypeName(string_mcode name)
+ | Ast0.MetaType(name,pure) ->
+ Ast0.MetaType(meta_mcode name,pure)
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ Ast0.DisjType(string_mcode starter,List.map typeC types,
+ List.map string_mcode mids,string_mcode ender)
+ | Ast0.OptType(ty) -> Ast0.OptType(typeC ty)
+ | Ast0.UniqueType(ty) -> Ast0.UniqueType(typeC ty)) in
+ tyfn all_functions k t
+ and declaration d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ Ast0.Init(get_option storage_mcode stg,
+ typeC ty, ident id, string_mcode eq, initialiser ini,
+ string_mcode sem)
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ Ast0.UnInit(get_option storage_mcode stg,
+ typeC ty, ident id, string_mcode sem)
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ Ast0.MacroDecl(ident name,string_mcode lp,
+ expression_dots args,
+ string_mcode rp,string_mcode sem)
+ | Ast0.TyDecl(ty,sem) -> Ast0.TyDecl(typeC ty, string_mcode sem)
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ Ast0.Typedef(string_mcode stg, typeC ty, typeC id,
+ string_mcode sem)
+ | Ast0.DisjDecl(starter,decls,mids,ender) ->
+ Ast0.DisjDecl(string_mcode starter,List.map declaration decls,
+ List.map string_mcode mids,string_mcode ender)
+ | Ast0.Ddots(dots,whencode) ->
+ Ast0.Ddots(string_mcode dots, get_option declaration whencode)
+ | Ast0.OptDecl(decl) -> Ast0.OptDecl(declaration decl)
+ | Ast0.UniqueDecl(decl) -> Ast0.UniqueDecl(declaration decl)) in
+ declfn all_functions k d
+ and initialiser i =
+ let k i =
+ Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> Ast0.InitExpr(expression exp)
+ | Ast0.InitList(lb,initlist,rb) ->
+ Ast0.InitList(string_mcode lb, initialiser_list initlist,
+ string_mcode rb)
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ Ast0.InitGccDotName
+ (string_mcode dot, ident name, string_mcode eq, initialiser ini)
+ | Ast0.InitGccName(name,eq,ini) ->
+ Ast0.InitGccName(ident name, string_mcode eq, initialiser ini)
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ Ast0.InitGccIndex
+ (string_mcode lb, expression exp, string_mcode rb,
+ string_mcode eq, initialiser ini)
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ Ast0.InitGccRange
+ (string_mcode lb, expression exp1, string_mcode dots,
+ expression exp2, string_mcode rb, string_mcode eq,
+ initialiser ini)
+ | Ast0.IComma(cm) -> Ast0.IComma(string_mcode cm)
+ | Ast0.Idots(d,whencode) ->
+ Ast0.Idots(string_mcode d, get_option initialiser whencode)
+ | Ast0.OptIni(i) -> Ast0.OptIni(initialiser i)
+ | Ast0.UniqueIni(i) -> Ast0.UniqueIni(initialiser i)) in
+ initfn all_functions k i
+ and parameterTypeDef p =
+ let k p =
+ Ast0.rewrap p
+ (match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> Ast0.VoidParam(typeC ty)
+ | Ast0.Param(ty,id) -> Ast0.Param(typeC ty, get_option ident id)
+ | Ast0.MetaParam(name,pure) ->
+ Ast0.MetaParam(meta_mcode name,pure)
+ | Ast0.MetaParamList(name,lenname,pure) ->
+ Ast0.MetaParamList(meta_mcode name,lenname,pure)
+ | Ast0.PComma(cm) -> Ast0.PComma(string_mcode cm)
+ | Ast0.Pdots(dots) -> Ast0.Pdots(string_mcode dots)
+ | Ast0.Pcircles(dots) -> Ast0.Pcircles(string_mcode dots)
+ | Ast0.OptParam(param) -> Ast0.OptParam(parameterTypeDef param)
+ | Ast0.UniqueParam(param) ->
+ Ast0.UniqueParam(parameterTypeDef param)) in
+ paramfn all_functions k p
+ (* not done for combiner, because the statement is assumed to be already
+ represented elsewhere in the code *)
+ and process_bef_aft s =
+ Ast0.set_dots_bef_aft s
+ (match Ast0.get_dots_bef_aft s with
+ Ast0.NoDots -> Ast0.NoDots
+ | Ast0.DroppingBetweenDots(stm) ->
+ Ast0.DroppingBetweenDots(statement stm)
+ | Ast0.AddingBetweenDots(stm) ->
+ Ast0.AddingBetweenDots(statement stm))
+
+ and statement s =
+ let k s =
+ Ast0.rewrap s
+ (match Ast0.unwrap s with
+ Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ Ast0.FunDecl(bef,List.map fninfo fi, ident name,
+ string_mcode lp, parameter_list params,
+ string_mcode rp, string_mcode lbrace,
+ statement_dots body, string_mcode rbrace)
+ | Ast0.Decl(bef,decl) -> Ast0.Decl(bef,declaration decl)
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ Ast0.Seq(string_mcode lbrace, statement_dots body,
+ string_mcode rbrace)
+ | Ast0.ExprStatement(exp,sem) ->
+ Ast0.ExprStatement(expression exp, string_mcode sem)
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,aft) ->
+ Ast0.IfThen(string_mcode iff, string_mcode lp, expression exp,
+ string_mcode rp, statement branch1,aft)
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
+ Ast0.IfThenElse(string_mcode iff,string_mcode lp,expression exp,
+ string_mcode rp, statement branch1, string_mcode els,
+ statement branch2,aft)
+ | Ast0.While(whl,lp,exp,rp,body,aft) ->
+ Ast0.While(string_mcode whl, string_mcode lp, expression exp,
+ string_mcode rp, statement body, aft)
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
+ Ast0.Do(string_mcode d, statement body, string_mcode whl,
+ string_mcode lp, expression exp, string_mcode rp,
+ string_mcode sem)
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,aft) ->
+ Ast0.For(string_mcode fr, string_mcode lp,
+ get_option expression e1, string_mcode sem1,
+ get_option expression e2, string_mcode sem2,
+ get_option expression e3,
+ string_mcode rp, statement body, aft)
+ | Ast0.Iterator(nm,lp,args,rp,body,aft) ->
+ Ast0.Iterator(ident nm, string_mcode lp,
+ expression_dots args,
+ string_mcode rp, statement body, aft)
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ Ast0.Switch(string_mcode switch,string_mcode lp,expression exp,
+ string_mcode rp,string_mcode lb,
+ case_line_dots cases, string_mcode rb)
+ | Ast0.Break(br,sem) ->
+ Ast0.Break(string_mcode br,string_mcode sem)
+ | Ast0.Continue(cont,sem) ->
+ Ast0.Continue(string_mcode cont,string_mcode sem)
+ | Ast0.Label(l,dd) -> Ast0.Label(ident l,string_mcode dd)
+ | Ast0.Goto(goto,l,sem) ->
+ Ast0.Goto(string_mcode goto,ident l,string_mcode sem)
+ | Ast0.Return(ret,sem) ->
+ Ast0.Return(string_mcode ret,string_mcode sem)
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ Ast0.ReturnExpr(string_mcode ret,expression exp,string_mcode sem)
+ | Ast0.MetaStmt(name,pure) ->
+ Ast0.MetaStmt(meta_mcode name,pure)
+ | Ast0.MetaStmtList(name,pure) ->
+ Ast0.MetaStmtList(meta_mcode name,pure)
+ | Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ Ast0.Disj(string_mcode starter,
+ List.map statement_dots statement_dots_list,
+ List.map string_mcode mids,
+ string_mcode ender)
+ | Ast0.Nest(starter,stmt_dots,ender,whn,multi) ->
+ Ast0.Nest(string_mcode starter,statement_dots stmt_dots,
+ string_mcode ender,
+ List.map (whencode statement_dots statement) whn,
+ multi)
+ | Ast0.Exp(exp) -> Ast0.Exp(expression exp)
+ | Ast0.TopExp(exp) -> Ast0.TopExp(expression exp)
+ | Ast0.Ty(ty) -> Ast0.Ty(typeC ty)
+ | Ast0.Dots(d,whn) ->
+ Ast0.Dots(string_mcode d,
+ List.map (whencode statement_dots statement) whn)
+ | Ast0.Circles(d,whn) ->
+ Ast0.Circles(string_mcode d,
+ List.map (whencode statement_dots statement) whn)
+ | Ast0.Stars(d,whn) ->
+ Ast0.Stars(string_mcode d,
+ List.map (whencode statement_dots statement) whn)
+ | Ast0.Include(inc,name) ->
+ Ast0.Include(string_mcode inc,inc_mcode name)
+ | Ast0.Define(def,id,params,body) ->
+ Ast0.Define(string_mcode def,ident id,
+ define_parameters params,
+ statement_dots body)
+ | Ast0.OptStm(re) -> Ast0.OptStm(statement re)
+ | Ast0.UniqueStm(re) -> Ast0.UniqueStm(statement re)) in
+ let s = stmtfn all_functions k s in
+ process_bef_aft s
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ Ast0.rewrap p
+ (match Ast0.unwrap p with
+ Ast0.NoParams -> Ast0.NoParams
+ | Ast0.DParams(lp,params,rp) ->
+ Ast0.DParams(string_mcode lp,define_param_dots params,
+ string_mcode rp))in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map define_param l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map define_param l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map define_param l)) in
+ k d
+
+ and define_param p =
+ let k p =
+ Ast0.rewrap p
+ (match Ast0.unwrap p with
+ Ast0.DParam(id) -> Ast0.DParam(ident id)
+ | Ast0.DPComma(comma) -> Ast0.DPComma(string_mcode comma)
+ | Ast0.DPdots(d) -> Ast0.DPdots(string_mcode d)
+ | Ast0.DPcircles(c) -> Ast0.DPcircles(string_mcode c)
+ | Ast0.OptDParam(dp) -> Ast0.OptDParam(define_param dp)
+ | Ast0.UniqueDParam(dp) -> Ast0.UniqueDParam(define_param dp)) in
+ k p
+
+ and fninfo = function
+ Ast0.FStorage(stg) -> Ast0.FStorage(storage_mcode stg)
+ | Ast0.FType(ty) -> Ast0.FType(typeC ty)
+ | Ast0.FInline(inline) -> Ast0.FInline(string_mcode inline)
+ | Ast0.FAttr(init) -> Ast0.FAttr(string_mcode init)
+
+ and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> Ast0.WhenNot (notfn a)
+ | Ast0.WhenAlways a -> Ast0.WhenAlways (alwaysfn a)
+ | Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
+
+ and case_line c =
+ let k c =
+ Ast0.rewrap c
+ (match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ Ast0.Default(string_mcode def,string_mcode colon,
+ statement_dots code)
+ | Ast0.Case(case,exp,colon,code) ->
+ Ast0.Case(string_mcode case,expression exp,string_mcode colon,
+ statement_dots code)
+ | Ast0.OptCase(case) -> Ast0.OptCase(case_line case)) in
+ casefn all_functions k c
+
+ and top_level t =
+ let k t =
+ Ast0.rewrap t
+ (match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ Ast0.FILEINFO(string_mcode old_file, string_mcode new_file)
+ | Ast0.DECL(statement_dots) ->
+ Ast0.DECL(statement statement_dots)
+ | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots stmt_dots)
+ | Ast0.ERRORWORDS(exps) -> Ast0.ERRORWORDS(List.map expression exps)
+ | Ast0.OTHER(_) -> failwith "unexpected code") in
+ topfn all_functions k t
+
+ and anything a = (* for compile_iso, not parameterisable *)
+ let k = function
+ Ast0.DotsExprTag(exprs) -> Ast0.DotsExprTag(expression_dots exprs)
+ | Ast0.DotsInitTag(inits) -> Ast0.DotsInitTag(initialiser_list inits)
+ | Ast0.DotsParamTag(params) -> Ast0.DotsParamTag(parameter_list params)
+ | Ast0.DotsStmtTag(stmts) -> Ast0.DotsStmtTag(statement_dots stmts)
+ | Ast0.DotsDeclTag(decls) -> Ast0.DotsDeclTag(declaration_dots decls)
+ | Ast0.DotsCaseTag(cases) -> Ast0.DotsCaseTag(case_line_dots cases)
+ | Ast0.IdentTag(id) -> Ast0.IdentTag(ident id)
+ | Ast0.ExprTag(exp) -> Ast0.ExprTag(expression exp)
+ | Ast0.ArgExprTag(exp) -> Ast0.ArgExprTag(expression exp)
+ | Ast0.TestExprTag(exp) -> Ast0.TestExprTag(expression exp)
+ | Ast0.TypeCTag(ty) -> Ast0.TypeCTag(typeC ty)
+ | Ast0.ParamTag(param) -> Ast0.ParamTag(parameterTypeDef param)
+ | Ast0.InitTag(init) -> Ast0.InitTag(initialiser init)
+ | Ast0.DeclTag(decl) -> Ast0.DeclTag(declaration decl)
+ | Ast0.StmtTag(stmt) -> Ast0.StmtTag(statement stmt)
+ | Ast0.CaseLineTag(c) -> Ast0.CaseLineTag(case_line c)
+ | Ast0.TopTag(top) -> Ast0.TopTag(top_level top)
+ | Ast0.IsoWhenTag(x) -> Ast0.IsoWhenTag(x)
+ | Ast0.MetaPosTag(var) -> failwith "not supported" in
+ k a
+
+ (* not done for combiner, because the statement is assumed to be already
+ represented elsewhere in the code *)
+
+ and all_functions =
+ {rebuilder_ident = ident;
+ rebuilder_expression = expression;
+ rebuilder_typeC = typeC;
+ rebuilder_declaration = declaration;
+ rebuilder_initialiser = initialiser;
+ rebuilder_initialiser_list = initialiser_list;
+ rebuilder_parameter = parameterTypeDef;
+ rebuilder_parameter_list = parameter_list;
+ rebuilder_statement = statement;
+ rebuilder_case_line = case_line;
+ rebuilder_top_level = top_level;
+ rebuilder_expression_dots = expression_dots;
+ rebuilder_statement_dots = statement_dots;
+ rebuilder_declaration_dots = declaration_dots;
+ rebuilder_case_line_dots = case_line_dots;
+ rebuilder_anything = anything} in
+ all_functions
--- /dev/null
+(*
+* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
+* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
+* This file is part of Coccinelle.
+*
+* Coccinelle is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, according to version 2 of the License.
+*
+* Coccinelle is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
+*
+* The authors reserve the right to distribute this or future versions of
+* Coccinelle under other licenses.
+*)
+
+
+module Ast = Ast_cocci
+module Ast0 = Ast0_cocci
+
+(* --------------------------------------------------------------------- *)
+(* Generic traversal: combiner *)
+(* parameters:
+ combining function
+ treatment of: mcode, identifiers, expressions, typeCs, types,
+ declarations, statements, toplevels
+ default value for options *)
+
+type 'a combiner =
+ {combiner_ident : Ast0.ident -> 'a;
+ combiner_expression : Ast0.expression -> 'a;
+ combiner_typeC : Ast0.typeC -> 'a;
+ combiner_declaration : Ast0.declaration -> 'a;
+ combiner_initialiser : Ast0.initialiser -> 'a;
+ combiner_initialiser_list : Ast0.initialiser_list -> 'a;
+ combiner_parameter : Ast0.parameterTypeDef -> 'a;
+ combiner_parameter_list : Ast0.parameter_list -> 'a;
+ combiner_statement : Ast0.statement -> 'a;
+ combiner_case_line : Ast0.case_line -> 'a;
+ combiner_top_level : Ast0.top_level -> 'a;
+ combiner_expression_dots :
+ Ast0.expression Ast0.dots -> 'a;
+ combiner_statement_dots :
+ Ast0.statement Ast0.dots -> 'a;
+ combiner_declaration_dots :
+ Ast0.declaration Ast0.dots -> 'a;
+ combiner_case_line_dots :
+ Ast0.case_line Ast0.dots -> 'a;
+ combiner_anything : Ast0.anything -> 'a}
+
+
+type ('mc,'a) cmcode = 'mc Ast0.mcode -> 'a
+type ('cd,'a) ccode = 'a combiner -> ('cd -> 'a) -> 'cd -> 'a
+
+let combiner bind option_default
+ meta_mcode string_mcode const_mcode assign_mcode fix_mcode unary_mcode
+ binary_mcode cv_mcode base_mcode sign_mcode struct_mcode storage_mcode
+ inc_mcode
+ dotsexprfn dotsinitfn dotsparamfn dotsstmtfn dotsdeclfn dotscasefn
+ identfn exprfn
+ tyfn initfn paramfn declfn stmtfn casefn topfn =
+ let multibind l =
+ let rec loop = function
+ [] -> option_default
+ | [x] -> x
+ | x::xs -> bind x (loop xs) in
+ loop l in
+ let get_option f = function
+ Some x -> f x
+ | None -> option_default in
+ let rec expression_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map expression l) in
+ dotsexprfn all_functions k d
+ and initialiser_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map initialiser l) in
+ dotsinitfn all_functions k d
+ and parameter_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map parameterTypeDef l) in
+ dotsparamfn all_functions k d
+ and statement_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map statement l) in
+ dotsstmtfn all_functions k d
+ and declaration_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map declaration l) in
+ dotsdeclfn all_functions k d
+ and case_line_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map case_line l) in
+ dotscasefn all_functions k d
+ and ident i =
+ let k i =
+ match Ast0.unwrap i with
+ Ast0.Id(name) -> string_mcode name
+ | Ast0.MetaId(name,_,_) -> meta_mcode name
+ | Ast0.MetaFunc(name,_,_) -> meta_mcode name
+ | Ast0.MetaLocalFunc(name,_,_) -> meta_mcode name
+ | Ast0.OptIdent(id) -> ident id
+ | Ast0.UniqueIdent(id) -> ident id in
+ identfn all_functions k i
+ and expression e =
+ let k e =
+ match Ast0.unwrap e with
+ Ast0.Ident(id) -> ident id
+ | Ast0.Constant(const) -> const_mcode const
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ multibind
+ [expression fn; string_mcode lp; expression_dots args;
+ string_mcode rp]
+ | Ast0.Assignment(left,op,right,_) ->
+ multibind [expression left; assign_mcode op; expression right]
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ multibind
+ [expression exp1; string_mcode why; get_option expression exp2;
+ string_mcode colon; expression exp3]
+ | Ast0.Postfix(exp,op) -> bind (expression exp) (fix_mcode op)
+ | Ast0.Infix(exp,op) -> bind (fix_mcode op) (expression exp)
+ | Ast0.Unary(exp,op) -> bind (unary_mcode op) (expression exp)
+ | Ast0.Binary(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast0.Nested(left,op,right) ->
+ multibind [expression left; binary_mcode op; expression right]
+ | Ast0.Paren(lp,exp,rp) ->
+ multibind [string_mcode lp; expression exp; string_mcode rp]
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ multibind
+ [expression exp1; string_mcode lb; expression exp2;
+ string_mcode rb]
+ | Ast0.RecordAccess(exp,pt,field) ->
+ multibind [expression exp; string_mcode pt; ident field]
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ multibind [expression exp; string_mcode ar; ident field]
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ multibind
+ [string_mcode lp; typeC ty; string_mcode rp; expression exp]
+ | Ast0.SizeOfExpr(szf,exp) ->
+ multibind [string_mcode szf; expression exp]
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ multibind
+ [string_mcode szf; string_mcode lp; typeC ty; string_mcode rp]
+ | Ast0.TypeExp(ty) -> typeC ty
+ | Ast0.MetaErr(name,_,_)
+ | Ast0.MetaExpr(name,_,_,_,_)
+ | Ast0.MetaExprList(name,_,_) -> meta_mcode name
+ | Ast0.EComma(cm) -> string_mcode cm
+ | Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ (match expr_list with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (expression x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (expression x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ bind (string_mcode starter)
+ (bind (expression_dots expr_dots)
+ (bind (string_mcode ender) (get_option expression whencode)))
+ | Ast0.Edots(dots,whencode) | Ast0.Ecircles(dots,whencode)
+ | Ast0.Estars(dots,whencode) ->
+ bind (string_mcode dots) (get_option expression whencode)
+ | Ast0.OptExp(exp) -> expression exp
+ | Ast0.UniqueExp(exp) -> expression exp in
+ exprfn all_functions k e
+ and function_pointer (ty,lp1,star,rp1,lp2,params,rp2) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind
+ ([typeC ty; string_mcode lp1; string_mcode star] @ extra @
+ [string_mcode rp1;
+ string_mcode lp2; parameter_dots params; string_mcode rp2])
+ and function_type (ty,lp1,params,rp1) extra =
+ (* have to put the treatment of the identifier into the right position *)
+ multibind ([get_option typeC ty] @ extra @
+ [string_mcode lp1; parameter_dots params; string_mcode rp1])
+ and array_type (ty,lb,size,rb) extra =
+ multibind
+ ([typeC ty] @ extra @
+ [string_mcode lb; get_option expression size; string_mcode rb])
+ and typeC t =
+ let k t =
+ match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> bind (cv_mcode cv) (typeC ty)
+ | Ast0.BaseType(ty,sign) ->
+ bind (get_option sign_mcode sign) (base_mcode ty)
+ | Ast0.ImplicitInt(sign) -> (sign_mcode sign)
+ | Ast0.Pointer(ty,star) -> bind (typeC ty) (string_mcode star)
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) []
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) []
+ | Ast0.Array(ty,lb,size,rb) ->
+ array_type (ty,lb,size,rb) []
+ | Ast0.StructUnionName(kind,name) ->
+ bind (struct_mcode kind) (get_option ident name)
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ multibind
+ [typeC ty;string_mcode lb;declaration_dots decls;string_mcode rb]
+ | Ast0.TypeName(name) -> string_mcode name
+ | Ast0.MetaType(name,_) -> meta_mcode name
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ (match types with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (typeC x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (typeC x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.OptType(ty) -> typeC ty
+ | Ast0.UniqueType(ty) -> typeC ty in
+ tyfn all_functions k t
+ and named_type ty id =
+ match Ast0.unwrap ty with
+ Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ function_pointer (ty,lp1,star,rp1,lp2,params,rp2) [ident id]
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ function_type (ty,lp1,params,rp1) [ident id]
+ | Ast0.Array(ty,lb,size,rb) ->
+ array_type (ty,lb,size,rb) [ident id]
+ | _ -> bind (typeC ty) (ident id)
+ and declaration d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id)
+ (multibind
+ [string_mcode eq; initialiser ini; string_mcode sem]))
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ bind (get_option storage_mcode stg)
+ (bind (named_type ty id) (string_mcode sem))
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ multibind
+ [ident name; string_mcode lp; expression_dots args;
+ string_mcode rp; string_mcode sem]
+ | Ast0.TyDecl(ty,sem) -> bind (typeC ty) (string_mcode sem)
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ bind (string_mcode stg)
+ (bind (typeC ty) (bind (typeC id) (string_mcode sem)))
+ | Ast0.DisjDecl(starter,decls,mids,ender) ->
+ (match decls with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (declaration x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (declaration x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.Ddots(dots,whencode) ->
+ bind (string_mcode dots) (get_option declaration whencode)
+ | Ast0.OptDecl(decl) -> declaration decl
+ | Ast0.UniqueDecl(decl) -> declaration decl in
+ declfn all_functions k d
+ and initialiser i =
+ let k i =
+ match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> expression exp
+ | Ast0.InitList(lb,initlist,rb) ->
+ multibind
+ [string_mcode lb; initialiser_dots initlist; string_mcode rb]
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ multibind
+ [string_mcode dot; ident name; string_mcode eq; initialiser ini]
+ | Ast0.InitGccName(name,eq,ini) ->
+ multibind [ident name; string_mcode eq; initialiser ini]
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp; string_mcode rb;
+ string_mcode eq; initialiser ini]
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ multibind
+ [string_mcode lb; expression exp1; string_mcode dots;
+ expression exp2; string_mcode rb; string_mcode eq;
+ initialiser ini]
+ | Ast0.IComma(cm) -> string_mcode cm
+ | Ast0.Idots(dots,whencode) ->
+ bind (string_mcode dots) (get_option initialiser whencode)
+ | Ast0.OptIni(i) -> initialiser i
+ | Ast0.UniqueIni(i) -> initialiser i in
+ initfn all_functions k i
+ and parameterTypeDef p =
+ let k p =
+ match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> typeC ty
+ | Ast0.Param(ty,Some id) -> named_type ty id
+ | Ast0.Param(ty,None) -> typeC ty
+ | Ast0.MetaParam(name,_) -> meta_mcode name
+ | Ast0.MetaParamList(name,_,_) -> meta_mcode name
+ | Ast0.PComma(cm) -> string_mcode cm
+ | Ast0.Pdots(dots) -> string_mcode dots
+ | Ast0.Pcircles(dots) -> string_mcode dots
+ | Ast0.OptParam(param) -> parameterTypeDef param
+ | Ast0.UniqueParam(param) -> parameterTypeDef param in
+ paramfn all_functions k p
+
+ (* discard the result, because the statement is assumed to be already
+ represented elsewhere in the code *)
+ and process_bef_aft s =
+ match Ast0.get_dots_bef_aft s with
+ Ast0.NoDots -> ()
+ | Ast0.DroppingBetweenDots(stm) -> let _ = statement stm in ()
+ | Ast0.AddingBetweenDots(stm) -> let _ = statement stm in ()
+
+ and statement s =
+ process_bef_aft s;
+ let k s =
+ match Ast0.unwrap s with
+ Ast0.FunDecl(_,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ multibind
+ ((List.map fninfo fi) @
+ [ident name; string_mcode lp;
+ parameter_dots params; string_mcode rp; string_mcode lbrace;
+ statement_dots body; string_mcode rbrace])
+ | Ast0.Decl(_,decl) -> declaration decl
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ multibind
+ [string_mcode lbrace; statement_dots body; string_mcode rbrace]
+ | Ast0.ExprStatement(exp,sem) ->
+ bind (expression exp) (string_mcode sem)
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,_) ->
+ multibind
+ [string_mcode iff; string_mcode lp; expression exp;
+ string_mcode rp; statement branch1]
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,_) ->
+ multibind
+ [string_mcode iff; string_mcode lp; expression exp;
+ string_mcode rp; statement branch1; string_mcode els;
+ statement branch2]
+ | Ast0.While(whl,lp,exp,rp,body,_) ->
+ multibind
+ [string_mcode whl; string_mcode lp; expression exp;
+ string_mcode rp; statement body]
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
+ multibind
+ [string_mcode d; statement body; string_mcode whl;
+ string_mcode lp; expression exp; string_mcode rp;
+ string_mcode sem]
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,_) ->
+ multibind
+ [string_mcode fr; string_mcode lp; get_option expression e1;
+ string_mcode sem1; get_option expression e2; string_mcode sem2;
+ get_option expression e3;
+ string_mcode rp; statement body]
+ | Ast0.Iterator(nm,lp,args,rp,body,_) ->
+ multibind
+ [ident nm; string_mcode lp; expression_dots args;
+ string_mcode rp; statement body]
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ multibind
+ [string_mcode switch; string_mcode lp; expression exp;
+ string_mcode rp; string_mcode lb; case_line_dots cases;
+ string_mcode rb]
+ | Ast0.Break(br,sem) -> bind (string_mcode br) (string_mcode sem)
+ | Ast0.Continue(cont,sem) -> bind (string_mcode cont) (string_mcode sem)
+ | Ast0.Label(l,dd) -> bind (ident l) (string_mcode dd)
+ | Ast0.Goto(goto,l,sem) ->
+ bind (string_mcode goto) (bind (ident l) (string_mcode sem))
+ | Ast0.Return(ret,sem) -> bind (string_mcode ret) (string_mcode sem)
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ multibind [string_mcode ret; expression exp; string_mcode sem]
+ | Ast0.MetaStmt(name,_) -> meta_mcode name
+ | Ast0.MetaStmtList(name,_) -> meta_mcode name
+ | Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ (match statement_dots_list with
+ [] -> failwith "bad disjunction"
+ | x::xs ->
+ bind (string_mcode starter)
+ (bind (statement_dots x)
+ (bind
+ (multibind
+ (List.map2
+ (function mid ->
+ function x ->
+ bind (string_mcode mid) (statement_dots x))
+ mids xs))
+ (string_mcode ender))))
+ | Ast0.Nest(starter,stmt_dots,ender,whn,multi) ->
+ bind (string_mcode starter)
+ (bind (statement_dots stmt_dots)
+ (bind (string_mcode ender)
+ (multibind
+ (List.map (whencode statement_dots statement) whn))))
+ | Ast0.Exp(exp) -> expression exp
+ | Ast0.TopExp(exp) -> expression exp
+ | Ast0.Ty(ty) -> typeC ty
+ | Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
+ bind (string_mcode d)
+ (multibind (List.map (whencode statement_dots statement) whn))
+ | Ast0.Include(inc,name) -> bind (string_mcode inc) (inc_mcode name)
+ | Ast0.Define(def,id,params,body) ->
+ multibind [string_mcode def; ident id; define_parameters params;
+ statement_dots body]
+ | Ast0.OptStm(re) -> statement re
+ | Ast0.UniqueStm(re) -> statement re in
+ stmtfn all_functions k s
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ match Ast0.unwrap p with
+ Ast0.NoParams -> option_default
+ | Ast0.DParams(lp,params,rp) ->
+ multibind
+ [string_mcode lp; define_param_dots params; string_mcode rp] in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ match Ast0.unwrap d with
+ Ast0.DOTS(l) | Ast0.CIRCLES(l) | Ast0.STARS(l) ->
+ multibind (List.map define_param l) in
+ k d
+
+ and define_param p =
+ let k p =
+ match Ast0.unwrap p with
+ Ast0.DParam(id) -> ident id
+ | Ast0.DPComma(comma) -> string_mcode comma
+ | Ast0.DPdots(d) -> string_mcode d
+ | Ast0.DPcircles(c) -> string_mcode c
+ | Ast0.OptDParam(dp) -> define_param dp
+ | Ast0.UniqueDParam(dp) -> define_param dp in
+ k p
+
+ and fninfo = function
+ Ast0.FStorage(stg) -> storage_mcode stg
+ | Ast0.FType(ty) -> typeC ty
+ | Ast0.FInline(inline) -> string_mcode inline
+ | Ast0.FAttr(init) -> string_mcode init
+
+ and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> notfn a
+ | Ast0.WhenAlways a -> alwaysfn a
+ | Ast0.WhenModifier(_) -> option_default
+ | Ast0.WhenNotTrue(e) -> expression e
+ | Ast0.WhenNotFalse(e) -> expression e
+
+ and case_line c =
+ let k c =
+ match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ multibind [string_mcode def;string_mcode colon;statement_dots code]
+ | Ast0.Case(case,exp,colon,code) ->
+ multibind [string_mcode case;expression exp;string_mcode colon;
+ statement_dots code]
+ | Ast0.OptCase(case) -> case_line case in
+ casefn all_functions k c
+
+ and anything a = (* for compile_iso, not parameterisable *)
+ let k = function
+ Ast0.DotsExprTag(exprs) -> expression_dots exprs
+ | Ast0.DotsInitTag(inits) -> initialiser_dots inits
+ | Ast0.DotsParamTag(params) -> parameter_dots params
+ | Ast0.DotsStmtTag(stmts) -> statement_dots stmts
+ | Ast0.DotsDeclTag(decls) -> declaration_dots decls
+ | Ast0.DotsCaseTag(cases) -> case_line_dots cases
+ | Ast0.IdentTag(id) -> ident id
+ | Ast0.ExprTag(exp) -> expression exp
+ | Ast0.ArgExprTag(exp) -> expression exp
+ | Ast0.TestExprTag(exp) -> expression exp
+ | Ast0.TypeCTag(ty) -> typeC ty
+ | Ast0.ParamTag(param) -> parameterTypeDef param
+ | Ast0.InitTag(init) -> initialiser init
+ | Ast0.DeclTag(decl) -> declaration decl
+ | Ast0.StmtTag(stmt) -> statement stmt
+ | Ast0.CaseLineTag(c) -> case_line c
+ | Ast0.TopTag(top) -> top_level top
+ | Ast0.IsoWhenTag(_) -> option_default
+ | Ast0.IsoWhenTTag(e) -> expression e
+ | Ast0.IsoWhenFTag(e) -> expression e
+ | Ast0.MetaPosTag(var) -> failwith "not supported" in
+ k a
+
+ and top_level t =
+ let k t =
+ match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ bind (string_mcode old_file) (string_mcode new_file)
+ | Ast0.DECL(stmt_dots) -> statement stmt_dots
+ | Ast0.CODE(stmt_dots) -> statement_dots stmt_dots
+ | Ast0.ERRORWORDS(exps) -> multibind (List.map expression exps)
+ | Ast0.OTHER(_) -> failwith "unexpected code" in
+ topfn all_functions k t
+ and all_functions =
+ {combiner_ident = ident;
+ combiner_expression = expression;
+ combiner_typeC = typeC;
+ combiner_declaration = declaration;
+ combiner_initialiser = initialiser;
+ combiner_initialiser_list = initialiser_dots;
+ combiner_parameter = parameterTypeDef;
+ combiner_parameter_list = parameter_dots;
+ combiner_statement = statement;
+ combiner_case_line = case_line;
+ combiner_top_level = top_level;
+ combiner_expression_dots = expression_dots;
+ combiner_statement_dots = statement_dots;
+ combiner_declaration_dots = declaration_dots;
+ combiner_case_line_dots = case_line_dots;
+ combiner_anything = anything} in
+ all_functions
+
+(* --------------------------------------------------------------------- *)
+(* Generic traversal: rebuilder *)
+
+type 'a inout = 'a -> 'a (* for specifying the type of rebuilder *)
+
+type rebuilder =
+ {rebuilder_ident : Ast0.ident inout;
+ rebuilder_expression : Ast0.expression inout;
+ rebuilder_typeC : Ast0.typeC inout;
+ rebuilder_declaration : Ast0.declaration inout;
+ rebuilder_initialiser : Ast0.initialiser inout;
+ rebuilder_initialiser_list : Ast0.initialiser_list inout;
+ rebuilder_parameter : Ast0.parameterTypeDef inout;
+ rebuilder_parameter_list : Ast0.parameter_list inout;
+ rebuilder_statement : Ast0.statement inout;
+ rebuilder_case_line : Ast0.case_line inout;
+ rebuilder_top_level : Ast0.top_level inout;
+ rebuilder_expression_dots :
+ Ast0.expression Ast0.dots ->
+ Ast0.expression Ast0.dots;
+ rebuilder_statement_dots :
+ Ast0.statement Ast0.dots ->
+ Ast0.statement Ast0.dots;
+ rebuilder_declaration_dots :
+ Ast0.declaration Ast0.dots ->
+ Ast0.declaration Ast0.dots;
+ rebuilder_case_line_dots :
+ Ast0.case_line Ast0.dots ->
+ Ast0.case_line Ast0.dots;
+ rebuilder_anything :
+ Ast0.anything -> Ast0.anything}
+
+type 'mc rmcode = 'mc Ast0.mcode inout
+type 'cd rcode = rebuilder -> ('cd inout) -> 'cd inout
+
+let rebuilder = fun
+ meta_mcode string_mcode const_mcode assign_mcode fix_mcode unary_mcode
+ binary_mcode cv_mcode base_mcode sign_mcode struct_mcode storage_mcode
+ inc_mcode
+ dotsexprfn dotsinitfn dotsparamfn dotsstmtfn dotsdeclfn dotscasefn
+ identfn exprfn tyfn initfn paramfn declfn stmtfn casefn topfn ->
+ let get_option f = function
+ Some x -> Some (f x)
+ | None -> None in
+ let rec expression_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map expression l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map expression l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map expression l)) in
+ dotsexprfn all_functions k d
+ and initialiser_list i =
+ let k i =
+ Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map initialiser l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map initialiser l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map initialiser l)) in
+ dotsinitfn all_functions k i
+ and parameter_list d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map parameterTypeDef l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map parameterTypeDef l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map parameterTypeDef l)) in
+ dotsparamfn all_functions k d
+ and statement_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map statement l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map statement l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map statement l)) in
+ dotsstmtfn all_functions k d
+ and declaration_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map declaration l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map declaration l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map declaration l)) in
+ dotsdeclfn all_functions k d
+ and case_line_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map case_line l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map case_line l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map case_line l)) in
+ dotscasefn all_functions k d
+ and ident i =
+ let k i =
+ Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.Id(name) -> Ast0.Id(string_mcode name)
+ | Ast0.MetaId(name,constraints,pure) ->
+ Ast0.MetaId(meta_mcode name,constraints,pure)
+ | Ast0.MetaFunc(name,constraints,pure) ->
+ Ast0.MetaFunc(meta_mcode name,constraints,pure)
+ | Ast0.MetaLocalFunc(name,constraints,pure) ->
+ Ast0.MetaLocalFunc(meta_mcode name,constraints,pure)
+ | Ast0.OptIdent(id) -> Ast0.OptIdent(ident id)
+ | Ast0.UniqueIdent(id) -> Ast0.UniqueIdent(ident id)) in
+ identfn all_functions k i
+ and expression e =
+ let k e =
+ Ast0.rewrap e
+ (match Ast0.unwrap e with
+ Ast0.Ident(id) -> Ast0.Ident(ident id)
+ | Ast0.Constant(const) -> Ast0.Constant(const_mcode const)
+ | Ast0.FunCall(fn,lp,args,rp) ->
+ Ast0.FunCall(expression fn,string_mcode lp,expression_dots args,
+ string_mcode rp)
+ | Ast0.Assignment(left,op,right,simple) ->
+ Ast0.Assignment(expression left,assign_mcode op,expression right,
+ simple)
+ | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
+ Ast0.CondExpr(expression exp1, string_mcode why,
+ get_option expression exp2, string_mcode colon,
+ expression exp3)
+ | Ast0.Postfix(exp,op) -> Ast0.Postfix(expression exp, fix_mcode op)
+ | Ast0.Infix(exp,op) -> Ast0.Infix(expression exp, fix_mcode op)
+ | Ast0.Unary(exp,op) -> Ast0.Unary(expression exp, unary_mcode op)
+ | Ast0.Binary(left,op,right) ->
+ Ast0.Binary(expression left, binary_mcode op, expression right)
+ | Ast0.Nested(left,op,right) ->
+ Ast0.Nested(expression left, binary_mcode op, expression right)
+ | Ast0.Paren(lp,exp,rp) ->
+ Ast0.Paren(string_mcode lp, expression exp, string_mcode rp)
+ | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
+ Ast0.ArrayAccess(expression exp1,string_mcode lb,expression exp2,
+ string_mcode rb)
+ | Ast0.RecordAccess(exp,pt,field) ->
+ Ast0.RecordAccess(expression exp, string_mcode pt, ident field)
+ | Ast0.RecordPtAccess(exp,ar,field) ->
+ Ast0.RecordPtAccess(expression exp, string_mcode ar, ident field)
+ | Ast0.Cast(lp,ty,rp,exp) ->
+ Ast0.Cast(string_mcode lp, typeC ty, string_mcode rp,
+ expression exp)
+ | Ast0.SizeOfExpr(szf,exp) ->
+ Ast0.SizeOfExpr(string_mcode szf, expression exp)
+ | Ast0.SizeOfType(szf,lp,ty,rp) ->
+ Ast0.SizeOfType(string_mcode szf,string_mcode lp, typeC ty,
+ string_mcode rp)
+ | Ast0.TypeExp(ty) -> Ast0.TypeExp(typeC ty)
+ | Ast0.MetaErr(name,constraints,pure) ->
+ Ast0.MetaErr(meta_mcode name,constraints,pure)
+ | Ast0.MetaExpr(name,constraints,ty,form,pure) ->
+ Ast0.MetaExpr(meta_mcode name,constraints,ty,form,pure)
+ | Ast0.MetaExprList(name,lenname,pure) ->
+ Ast0.MetaExprList(meta_mcode name,lenname,pure)
+ | Ast0.EComma(cm) -> Ast0.EComma(string_mcode cm)
+ | Ast0.DisjExpr(starter,expr_list,mids,ender) ->
+ Ast0.DisjExpr(string_mcode starter,List.map expression expr_list,
+ List.map string_mcode mids,string_mcode ender)
+ | Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
+ Ast0.NestExpr(string_mcode starter,expression_dots expr_dots,
+ string_mcode ender, get_option expression whencode,
+ multi)
+ | Ast0.Edots(dots,whencode) ->
+ Ast0.Edots(string_mcode dots, get_option expression whencode)
+ | Ast0.Ecircles(dots,whencode) ->
+ Ast0.Ecircles(string_mcode dots, get_option expression whencode)
+ | Ast0.Estars(dots,whencode) ->
+ Ast0.Estars(string_mcode dots, get_option expression whencode)
+ | Ast0.OptExp(exp) -> Ast0.OptExp(expression exp)
+ | Ast0.UniqueExp(exp) -> Ast0.UniqueExp(expression exp)) in
+ exprfn all_functions k e
+ and typeC t =
+ let k t =
+ Ast0.rewrap t
+ (match Ast0.unwrap t with
+ Ast0.ConstVol(cv,ty) -> Ast0.ConstVol(cv_mcode cv,typeC ty)
+ | Ast0.BaseType(ty,sign) ->
+ Ast0.BaseType(base_mcode ty, get_option sign_mcode sign)
+ | Ast0.ImplicitInt(sign) -> Ast0.ImplicitInt(sign_mcode sign)
+ | Ast0.Pointer(ty,star) ->
+ Ast0.Pointer(typeC ty, string_mcode star)
+ | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
+ Ast0.FunctionPointer(typeC ty,string_mcode lp1,string_mcode star,
+ string_mcode rp1,string_mcode lp2,
+ parameter_list params,
+ string_mcode rp2)
+ | Ast0.FunctionType(ty,lp1,params,rp1) ->
+ Ast0.FunctionType(get_option typeC ty,
+ string_mcode lp1,parameter_list params,
+ string_mcode rp1)
+ | Ast0.Array(ty,lb,size,rb) ->
+ Ast0.Array(typeC ty, string_mcode lb,
+ get_option expression size, string_mcode rb)
+ | Ast0.StructUnionName(kind,name) ->
+ Ast0.StructUnionName (struct_mcode kind, get_option ident name)
+ | Ast0.StructUnionDef(ty,lb,decls,rb) ->
+ Ast0.StructUnionDef (typeC ty,
+ string_mcode lb, declaration_dots decls,
+ string_mcode rb)
+ | Ast0.TypeName(name) -> Ast0.TypeName(string_mcode name)
+ | Ast0.MetaType(name,pure) ->
+ Ast0.MetaType(meta_mcode name,pure)
+ | Ast0.DisjType(starter,types,mids,ender) ->
+ Ast0.DisjType(string_mcode starter,List.map typeC types,
+ List.map string_mcode mids,string_mcode ender)
+ | Ast0.OptType(ty) -> Ast0.OptType(typeC ty)
+ | Ast0.UniqueType(ty) -> Ast0.UniqueType(typeC ty)) in
+ tyfn all_functions k t
+ and declaration d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.Init(stg,ty,id,eq,ini,sem) ->
+ Ast0.Init(get_option storage_mcode stg,
+ typeC ty, ident id, string_mcode eq, initialiser ini,
+ string_mcode sem)
+ | Ast0.UnInit(stg,ty,id,sem) ->
+ Ast0.UnInit(get_option storage_mcode stg,
+ typeC ty, ident id, string_mcode sem)
+ | Ast0.MacroDecl(name,lp,args,rp,sem) ->
+ Ast0.MacroDecl(ident name,string_mcode lp,
+ expression_dots args,
+ string_mcode rp,string_mcode sem)
+ | Ast0.TyDecl(ty,sem) -> Ast0.TyDecl(typeC ty, string_mcode sem)
+ | Ast0.Typedef(stg,ty,id,sem) ->
+ Ast0.Typedef(string_mcode stg, typeC ty, typeC id,
+ string_mcode sem)
+ | Ast0.DisjDecl(starter,decls,mids,ender) ->
+ Ast0.DisjDecl(string_mcode starter,List.map declaration decls,
+ List.map string_mcode mids,string_mcode ender)
+ | Ast0.Ddots(dots,whencode) ->
+ Ast0.Ddots(string_mcode dots, get_option declaration whencode)
+ | Ast0.OptDecl(decl) -> Ast0.OptDecl(declaration decl)
+ | Ast0.UniqueDecl(decl) -> Ast0.UniqueDecl(declaration decl)) in
+ declfn all_functions k d
+ and initialiser i =
+ let k i =
+ Ast0.rewrap i
+ (match Ast0.unwrap i with
+ Ast0.InitExpr(exp) -> Ast0.InitExpr(expression exp)
+ | Ast0.InitList(lb,initlist,rb) ->
+ Ast0.InitList(string_mcode lb, initialiser_list initlist,
+ string_mcode rb)
+ | Ast0.InitGccDotName(dot,name,eq,ini) ->
+ Ast0.InitGccDotName
+ (string_mcode dot, ident name, string_mcode eq, initialiser ini)
+ | Ast0.InitGccName(name,eq,ini) ->
+ Ast0.InitGccName(ident name, string_mcode eq, initialiser ini)
+ | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
+ Ast0.InitGccIndex
+ (string_mcode lb, expression exp, string_mcode rb,
+ string_mcode eq, initialiser ini)
+ | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
+ Ast0.InitGccRange
+ (string_mcode lb, expression exp1, string_mcode dots,
+ expression exp2, string_mcode rb, string_mcode eq,
+ initialiser ini)
+ | Ast0.IComma(cm) -> Ast0.IComma(string_mcode cm)
+ | Ast0.Idots(d,whencode) ->
+ Ast0.Idots(string_mcode d, get_option initialiser whencode)
+ | Ast0.OptIni(i) -> Ast0.OptIni(initialiser i)
+ | Ast0.UniqueIni(i) -> Ast0.UniqueIni(initialiser i)) in
+ initfn all_functions k i
+ and parameterTypeDef p =
+ let k p =
+ Ast0.rewrap p
+ (match Ast0.unwrap p with
+ Ast0.VoidParam(ty) -> Ast0.VoidParam(typeC ty)
+ | Ast0.Param(ty,id) -> Ast0.Param(typeC ty, get_option ident id)
+ | Ast0.MetaParam(name,pure) ->
+ Ast0.MetaParam(meta_mcode name,pure)
+ | Ast0.MetaParamList(name,lenname,pure) ->
+ Ast0.MetaParamList(meta_mcode name,lenname,pure)
+ | Ast0.PComma(cm) -> Ast0.PComma(string_mcode cm)
+ | Ast0.Pdots(dots) -> Ast0.Pdots(string_mcode dots)
+ | Ast0.Pcircles(dots) -> Ast0.Pcircles(string_mcode dots)
+ | Ast0.OptParam(param) -> Ast0.OptParam(parameterTypeDef param)
+ | Ast0.UniqueParam(param) ->
+ Ast0.UniqueParam(parameterTypeDef param)) in
+ paramfn all_functions k p
+ (* not done for combiner, because the statement is assumed to be already
+ represented elsewhere in the code *)
+ and process_bef_aft s =
+ Ast0.set_dots_bef_aft s
+ (match Ast0.get_dots_bef_aft s with
+ Ast0.NoDots -> Ast0.NoDots
+ | Ast0.DroppingBetweenDots(stm) ->
+ Ast0.DroppingBetweenDots(statement stm)
+ | Ast0.AddingBetweenDots(stm) ->
+ Ast0.AddingBetweenDots(statement stm))
+
+ and statement s =
+ let k s =
+ Ast0.rewrap s
+ (match Ast0.unwrap s with
+ Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
+ Ast0.FunDecl(bef,List.map fninfo fi, ident name,
+ string_mcode lp, parameter_list params,
+ string_mcode rp, string_mcode lbrace,
+ statement_dots body, string_mcode rbrace)
+ | Ast0.Decl(bef,decl) -> Ast0.Decl(bef,declaration decl)
+ | Ast0.Seq(lbrace,body,rbrace) ->
+ Ast0.Seq(string_mcode lbrace, statement_dots body,
+ string_mcode rbrace)
+ | Ast0.ExprStatement(exp,sem) ->
+ Ast0.ExprStatement(expression exp, string_mcode sem)
+ | Ast0.IfThen(iff,lp,exp,rp,branch1,aft) ->
+ Ast0.IfThen(string_mcode iff, string_mcode lp, expression exp,
+ string_mcode rp, statement branch1,aft)
+ | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
+ Ast0.IfThenElse(string_mcode iff,string_mcode lp,expression exp,
+ string_mcode rp, statement branch1, string_mcode els,
+ statement branch2,aft)
+ | Ast0.While(whl,lp,exp,rp,body,aft) ->
+ Ast0.While(string_mcode whl, string_mcode lp, expression exp,
+ string_mcode rp, statement body, aft)
+ | Ast0.Do(d,body,whl,lp,exp,rp,sem) ->
+ Ast0.Do(string_mcode d, statement body, string_mcode whl,
+ string_mcode lp, expression exp, string_mcode rp,
+ string_mcode sem)
+ | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,aft) ->
+ Ast0.For(string_mcode fr, string_mcode lp,
+ get_option expression e1, string_mcode sem1,
+ get_option expression e2, string_mcode sem2,
+ get_option expression e3,
+ string_mcode rp, statement body, aft)
+ | Ast0.Iterator(nm,lp,args,rp,body,aft) ->
+ Ast0.Iterator(ident nm, string_mcode lp,
+ expression_dots args,
+ string_mcode rp, statement body, aft)
+ | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+ Ast0.Switch(string_mcode switch,string_mcode lp,expression exp,
+ string_mcode rp,string_mcode lb,
+ case_line_dots cases, string_mcode rb)
+ | Ast0.Break(br,sem) ->
+ Ast0.Break(string_mcode br,string_mcode sem)
+ | Ast0.Continue(cont,sem) ->
+ Ast0.Continue(string_mcode cont,string_mcode sem)
+ | Ast0.Label(l,dd) -> Ast0.Label(ident l,string_mcode dd)
+ | Ast0.Goto(goto,l,sem) ->
+ Ast0.Goto(string_mcode goto,ident l,string_mcode sem)
+ | Ast0.Return(ret,sem) ->
+ Ast0.Return(string_mcode ret,string_mcode sem)
+ | Ast0.ReturnExpr(ret,exp,sem) ->
+ Ast0.ReturnExpr(string_mcode ret,expression exp,string_mcode sem)
+ | Ast0.MetaStmt(name,pure) ->
+ Ast0.MetaStmt(meta_mcode name,pure)
+ | Ast0.MetaStmtList(name,pure) ->
+ Ast0.MetaStmtList(meta_mcode name,pure)
+ | Ast0.Disj(starter,statement_dots_list,mids,ender) ->
+ Ast0.Disj(string_mcode starter,
+ List.map statement_dots statement_dots_list,
+ List.map string_mcode mids,
+ string_mcode ender)
+ | Ast0.Nest(starter,stmt_dots,ender,whn,multi) ->
+ Ast0.Nest(string_mcode starter,statement_dots stmt_dots,
+ string_mcode ender,
+ List.map (whencode statement_dots statement) whn,
+ multi)
+ | Ast0.Exp(exp) -> Ast0.Exp(expression exp)
+ | Ast0.TopExp(exp) -> Ast0.TopExp(expression exp)
+ | Ast0.Ty(ty) -> Ast0.Ty(typeC ty)
+ | Ast0.Dots(d,whn) ->
+ Ast0.Dots(string_mcode d,
+ List.map (whencode statement_dots statement) whn)
+ | Ast0.Circles(d,whn) ->
+ Ast0.Circles(string_mcode d,
+ List.map (whencode statement_dots statement) whn)
+ | Ast0.Stars(d,whn) ->
+ Ast0.Stars(string_mcode d,
+ List.map (whencode statement_dots statement) whn)
+ | Ast0.Include(inc,name) ->
+ Ast0.Include(string_mcode inc,inc_mcode name)
+ | Ast0.Define(def,id,params,body) ->
+ Ast0.Define(string_mcode def,ident id,
+ define_parameters params,
+ statement_dots body)
+ | Ast0.OptStm(re) -> Ast0.OptStm(statement re)
+ | Ast0.UniqueStm(re) -> Ast0.UniqueStm(statement re)) in
+ let s = stmtfn all_functions k s in
+ process_bef_aft s
+
+ (* not parameterizable for now... *)
+ and define_parameters p =
+ let k p =
+ Ast0.rewrap p
+ (match Ast0.unwrap p with
+ Ast0.NoParams -> Ast0.NoParams
+ | Ast0.DParams(lp,params,rp) ->
+ Ast0.DParams(string_mcode lp,define_param_dots params,
+ string_mcode rp))in
+ k p
+
+ and define_param_dots d =
+ let k d =
+ Ast0.rewrap d
+ (match Ast0.unwrap d with
+ Ast0.DOTS(l) -> Ast0.DOTS(List.map define_param l)
+ | Ast0.CIRCLES(l) -> Ast0.CIRCLES(List.map define_param l)
+ | Ast0.STARS(l) -> Ast0.STARS(List.map define_param l)) in
+ k d
+
+ and define_param p =
+ let k p =
+ Ast0.rewrap p
+ (match Ast0.unwrap p with
+ Ast0.DParam(id) -> Ast0.DParam(ident id)
+ | Ast0.DPComma(comma) -> Ast0.DPComma(string_mcode comma)
+ | Ast0.DPdots(d) -> Ast0.DPdots(string_mcode d)
+ | Ast0.DPcircles(c) -> Ast0.DPcircles(string_mcode c)
+ | Ast0.OptDParam(dp) -> Ast0.OptDParam(define_param dp)
+ | Ast0.UniqueDParam(dp) -> Ast0.UniqueDParam(define_param dp)) in
+ k p
+
+ and fninfo = function
+ Ast0.FStorage(stg) -> Ast0.FStorage(storage_mcode stg)
+ | Ast0.FType(ty) -> Ast0.FType(typeC ty)
+ | Ast0.FInline(inline) -> Ast0.FInline(string_mcode inline)
+ | Ast0.FAttr(init) -> Ast0.FAttr(string_mcode init)
+
+ and whencode notfn alwaysfn = function
+ Ast0.WhenNot a -> Ast0.WhenNot (notfn a)
+ | Ast0.WhenAlways a -> Ast0.WhenAlways (alwaysfn a)
+ | Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
+ | Ast0.WhenNotTrue(e) -> Ast0.WhenNotTrue(expression e)
+ | Ast0.WhenNotFalse(e) -> Ast0.WhenNotFalse(expression e)
+
+ and case_line c =
+ let k c =
+ Ast0.rewrap c
+ (match Ast0.unwrap c with
+ Ast0.Default(def,colon,code) ->
+ Ast0.Default(string_mcode def,string_mcode colon,
+ statement_dots code)
+ | Ast0.Case(case,exp,colon,code) ->
+ Ast0.Case(string_mcode case,expression exp,string_mcode colon,
+ statement_dots code)
+ | Ast0.OptCase(case) -> Ast0.OptCase(case_line case)) in
+ casefn all_functions k c
+
+ and top_level t =
+ let k t =
+ Ast0.rewrap t
+ (match Ast0.unwrap t with
+ Ast0.FILEINFO(old_file,new_file) ->
+ Ast0.FILEINFO(string_mcode old_file, string_mcode new_file)
+ | Ast0.DECL(statement_dots) ->
+ Ast0.DECL(statement statement_dots)
+ | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots stmt_dots)
+ | Ast0.ERRORWORDS(exps) -> Ast0.ERRORWORDS(List.map expression exps)
+ | Ast0.OTHER(_) -> failwith "unexpected code") in
+ topfn all_functions k t
+
+ and anything a = (* for compile_iso, not parameterisable *)
+ let k = function
+ Ast0.DotsExprTag(exprs) -> Ast0.DotsExprTag(expression_dots exprs)
+ | Ast0.DotsInitTag(inits) -> Ast0.DotsInitTag(initialiser_list inits)
+ | Ast0.DotsParamTag(params) -> Ast0.DotsParamTag(parameter_list params)
+ | Ast0.DotsStmtTag(stmts) -> Ast0.DotsStmtTag(statement_dots stmts)
+ | Ast0.DotsDeclTag(decls) -> Ast0.DotsDeclTag(declaration_dots decls)
+ | Ast0.DotsCaseTag(cases) -> Ast0.DotsCaseTag(case_line_dots cases)
+ | Ast0.IdentTag(id) -> Ast0.IdentTag(ident id)
+ | Ast0.ExprTag(exp) -> Ast0.ExprTag(expression exp)
+ | Ast0.ArgExprTag(exp) -> Ast0.ArgExprTag(expression exp)
+ | Ast0.TestExprTag(exp) -> Ast0.TestExprTag(expression exp)
+ | Ast0.TypeCTag(ty) -> Ast0.TypeCTag(typeC ty)
+ | Ast0.ParamTag(param) -> Ast0.ParamTag(parameterTypeDef param)
+ | Ast0.InitTag(init) -> Ast0.InitTag(initialiser init)
+ | Ast0.DeclTag(decl) -> Ast0.DeclTag(declaration decl)
+ | Ast0.StmtTag(stmt) -> Ast0.StmtTag(statement stmt)
+ | Ast0.CaseLineTag(c) -> Ast0.CaseLineTag(case_line c)
+ | Ast0.TopTag(top) -> Ast0.TopTag(top_level top)
+ | Ast0.IsoWhenTag(x) -> Ast0.IsoWhenTag(x)
+ | Ast0.IsoWhenTTag(e) -> Ast0.IsoWhenTTag(expression e)
+ | Ast0.IsoWhenFTag(e) -> Ast0.IsoWhenFTag(expression e)
+ | Ast0.MetaPosTag(var) -> failwith "not supported" in
+ k a
+
+ (* not done for combiner, because the statement is assumed to be already
+ represented elsewhere in the code *)
+
+ and all_functions =
+ {rebuilder_ident = ident;
+ rebuilder_expression = expression;
+ rebuilder_typeC = typeC;
+ rebuilder_declaration = declaration;
+ rebuilder_initialiser = initialiser;
+ rebuilder_initialiser_list = initialiser_list;
+ rebuilder_parameter = parameterTypeDef;
+ rebuilder_parameter_list = parameter_list;
+ rebuilder_statement = statement;
+ rebuilder_case_line = case_line;
+ rebuilder_top_level = top_level;
+ rebuilder_expression_dots = expression_dots;
+ rebuilder_statement_dots = statement_dots;
+ rebuilder_declaration_dots = declaration_dots;
+ rebuilder_case_line_dots = case_line_dots;
+ rebuilder_anything = anything} in
+ all_functions
--- /dev/null
+.depend
+*.cma
+lexer_cocci.ml
+lexer_script.ml
+parser_cocci_menhir.ml
+parser_cocci_menhir.mli
| Ast0.UniqueType(ty) ->
Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Ty(ty)))
| _ -> Ast0.Ty(new_ty))
+ | Ast0.TopInit(init) ->
+ let new_init = initialiser tgt init in
+ Ast0.rewrap stm
+ (match Ast0.unwrap new_init with
+ Ast0.OptIni(init) ->
+ Ast0.OptStm(Ast0.rewrap stm (Ast0.TopInit(init)))
+ | Ast0.UniqueIni(init) ->
+ Ast0.UniqueStm(Ast0.rewrap stm (Ast0.TopInit(init)))
+ | _ -> Ast0.TopInit(new_init))
| Ast0.Disj(starter,rule_elem_dots_list,mids,ender) ->
let stms =
List.map (function x -> concat_dots (statement tgt) x)
concat_dots (statement Ast0.NONE) rule_elem_dots in
let whn =
List.map
- (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
whn in
Ast0.rewrap stm
(Ast0.Nest(starter,new_rule_elem_dots,ender,whn,multi))
let dots = mcode dots in
let whn =
List.map
- (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
whn in
make_rule_elem stm tgt arity (Ast0.Dots(dots,whn))
| Ast0.Circles(dots,whn) ->
let dots = mcode dots in
let whn =
List.map
- (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
whn in
make_rule_elem stm tgt arity (Ast0.Circles(dots,whn))
| Ast0.Stars(dots,whn) ->
let dots = mcode dots in
let whn =
List.map
- (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE))
+ (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
+ (expression Ast0.NONE))
whn in
make_rule_elem stm tgt arity (Ast0.Stars(dots,whn))
| Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
| Ast0.FAttr(attr) -> [mcode2arity attr])
fninfo)
-and whencode notfn alwaysfn = function
+and whencode notfn alwaysfn expression = function
Ast0.WhenNot a -> Ast0.WhenNot (notfn a)
| Ast0.WhenAlways a -> Ast0.WhenAlways (alwaysfn a)
| Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
+ | Ast0.WhenNotTrue a -> Ast0.WhenNotTrue (expression a)
+ | Ast0.WhenNotFalse a -> Ast0.WhenNotFalse (expression a)
and make_case_line =
make_opt_unique
| Exp of expression (* only in dotted statement lists *)
| TopExp of expression (* for macros body *)
| Ty of typeC (* only at top level *)
+ | TopInit of initialiser (* only at top level *)
| Disj of string mcode * statement dots list *
string mcode list (* the |s *) * string mcode
| Nest of string mcode * statement dots * string mcode *
WhenNot of 'a
| WhenAlways of 'b
| WhenModifier of Ast.when_modifier
+ | WhenNotTrue of expression
+ | WhenNotFalse of expression
and statement = base_statement wrap
| CaseLineTag of case_line
| TopTag of top_level
| IsoWhenTag of Ast.when_modifier
+ | IsoWhenTTag of expression
+ | IsoWhenFTag of expression
| MetaPosTag of meta_pos
let dotsExpr x = DotsExprTag x
| Exp of expression (* only in dotted statement lists *)
| TopExp of expression (* for macros body *)
| Ty of typeC (* only at top level *)
+ | TopInit of initialiser (* only at top level *)
| Disj of string mcode * statement dots list * string mcode list *
string mcode
| Nest of string mcode * statement dots * string mcode *
WhenNot of 'a
| WhenAlways of 'b
| WhenModifier of Ast_cocci.when_modifier
+ | WhenNotTrue of expression
+ | WhenNotFalse of expression
and statement = base_statement wrap
| CaseLineTag of case_line
| TopTag of top_level
| IsoWhenTag of Ast_cocci.when_modifier (*only for when code, in iso phase*)
+ | IsoWhenTTag of expression(*only for when code, in iso phase*)
+ | IsoWhenFTag of expression(*only for when code, in iso phase*)
| MetaPosTag of meta_pos (* only in iso phase *)
val dotsExpr : expression dots -> anything
Ast.Atomic(rewrap_rule_elem s (Ast.TopExp(expression exp)))
| Ast0.Exp(exp) ->
Ast.Atomic(rewrap_rule_elem s (Ast.Exp(expression exp)))
+ | Ast0.TopInit(init) ->
+ Ast.Atomic(rewrap_rule_elem s (Ast.TopInit(initialiser init)))
| Ast0.Ty(ty) ->
Ast.Atomic(rewrap_rule_elem s (Ast.Ty(typeC ty)))
| Ast0.Disj(_,rule_elem_dots_list,_,_) ->
Ast0.WhenNot a -> Ast.WhenNot (notfn a)
| Ast0.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
| Ast0.WhenModifier(x) -> Ast.WhenModifier(x)
+ | x ->
+ let rewrap_rule_elem ast0 ast =
+ rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
+ match x with
+ Ast0.WhenNotTrue(e) ->
+ Ast.WhenNotTrue(rewrap_rule_elem e (Ast.Exp(expression e)))
+ | Ast0.WhenNotFalse(e) ->
+ Ast.WhenNotFalse(rewrap_rule_elem e (Ast.Exp(expression e)))
+ | _ -> failwith "not possible"
and process_list seqible isos = function
[] -> []
| Ast0.CaseLineTag(d) -> Ast.CaseLineTag(case_line d)
| Ast0.TopTag(d) -> Ast.Code(top_level d)
| Ast0.IsoWhenTag(_) -> failwith "not possible"
+ | Ast0.IsoWhenTTag(_) -> failwith "not possible"
+ | Ast0.IsoWhenFTag(_) -> failwith "not possible"
| Ast0.MetaPosTag _ -> failwith "not possible"
(* --------------------------------------------------------------------- *)
| TopExp of expression (* for macros body, exp at top level,
not subexp *)
| Ty of fullType (* only at SP top level, matches a subterm *)
+ | TopInit of initialiser (* only at top level *)
| Include of string mcode (*#include*) * inc_file mcode (*file *)
| DefineHeader of string mcode (* #define *) * ident (* name *) *
define_parameters (*params*)
WhenNot of 'a
| WhenAlways of 'b
| WhenModifier of when_modifier
+ | WhenNotTrue of rule_elem (* useful for fvs *)
+ | WhenNotFalse of rule_elem
and when_modifier =
(* The following removes the shortest path constraint. It can be used
(function
WhenNot(a) -> get_fvs a
| WhenAlways(a) -> get_fvs a
- | WhenModifier(_) -> [])
+ | WhenModifier(_) -> []
+ | WhenNotTrue(e) -> get_fvs e
+ | WhenNotFalse(e) -> get_fvs e)
whencode)
(* --------------------------------------------------------------------- *)
| Exp of expression
| TopExp of expression (* for macros body *)
| Ty of fullType (* only at top level *)
+ | TopInit of initialiser (* only at top level *)
| Include of string mcode (*#include*) * inc_file mcode (*file *)
| DefineHeader of string mcode (* #define *) * ident (* name *) *
define_parameters (*params*)
WhenNot of 'a
| WhenAlways of 'b
| WhenModifier of when_modifier
+ | WhenNotTrue of rule_elem
+ | WhenNotFalse of rule_elem
and when_modifier =
WhenAny
| Ast0.Exp(exp) -> expression ID old_metas table minus exp
| Ast0.TopExp(exp) -> expression ID old_metas table minus exp
| Ast0.Ty(ty) -> typeC old_metas table minus ty
+ | Ast0.TopInit(init) -> initialiser old_metas table minus init
| Ast0.Disj(_,rule_elem_dots_list,_,_) ->
List.iter (dots (statement old_metas table minus)) rule_elem_dots_list
| Ast0.Nest(_,rule_elem_dots,_,w,_) ->
dots (statement old_metas table minus) rule_elem_dots;
List.iter (whencode (dots (statement old_metas table minus))
- (statement old_metas table minus))
+ (statement old_metas table minus)
+ (expression ID old_metas table minus))
w
| Ast0.Dots(_,x) | Ast0.Circles(_,x) | Ast0.Stars(_,x) ->
List.iter
(whencode (dots (statement old_metas table minus))
- (statement old_metas table minus)) x
+ (statement old_metas table minus)
+ (expression ID old_metas table minus)) x
| Ast0.FunDecl(_,fi,name,lp,params,rp,lbrace,body,rbrace) ->
ident FN old_metas table minus name;
List.iter (fninfo old_metas table minus) fi;
| Ast0.FInline(inline) -> ()
| Ast0.FAttr(attr) -> ()
-and whencode notfn alwaysfn = function
+and whencode notfn alwaysfn expression = function
Ast0.WhenNot a -> notfn a
| Ast0.WhenAlways a -> alwaysfn a
| Ast0.WhenModifier(_) -> ()
+ | Ast0.WhenNotTrue a -> expression a
+ | Ast0.WhenNotFalse a -> expression a
and case_line old_metas table minus c =
match Ast0.unwrap c with
| Ast0.Ty(ty) ->
let ty = typeC ty in
mkres s (Ast0.Ty(ty)) ty ty
+ | Ast0.TopInit(init) ->
+ let init = initialiser init in
+ mkres s (Ast0.TopInit(init)) init init
| Ast0.Disj(starter,rule_elem_dots_list,mids,ender) ->
let starter = bad_mcode starter in
let mids = List.map bad_mcode mids in
| Ast0.CaseLineTag(d) -> Ast0.set_mcodekind d mcodekind
| Ast0.TopTag(d) -> Ast0.set_mcodekind d mcodekind
| Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
| Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
let set_index x index =
| Ast0.CaseLineTag(d) -> Ast0.set_index d index
| Ast0.TopTag(d) -> Ast0.set_index d index
| Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
| Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
let get_index = function
| Ast0.CaseLineTag(d) -> Index.case_line d
| Ast0.TopTag(d) -> Index.top_level d
| Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
| Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
(* --------------------------------------------------------------------- *)
| (Ast0.Exp(_),Ast0.Exp(_)) -> true
| (Ast0.TopExp(_),Ast0.TopExp(_)) -> true
| (Ast0.Ty(_),Ast0.Ty(_)) -> true
+ | (Ast0.TopInit(_),Ast0.TopInit(_)) -> true
| (Ast0.Dots(d1,_),Ast0.Dots(d2,_))
| (Ast0.Circles(d1,_),Ast0.Circles(d2,_))
| (Ast0.Stars(d1,_),Ast0.Stars(d2,_)) -> equal_mcode d1 d2
| (Ast0.DeclTag(d1),Ast0.DeclTag(d2)) -> equal_declaration d1 d2
| (Ast0.StmtTag(s1),Ast0.StmtTag(s2)) -> equal_statement s1 s2
| (Ast0.TopTag(t1),Ast0.TopTag(t2)) -> equal_top_level t1 t2
- | (Ast0.IsoWhenTag(_),_) | (_,Ast0.IsoWhenTag(_)) ->
+ | (Ast0.IsoWhenTag(_),_) | (_,Ast0.IsoWhenTag(_))
+ | (Ast0.IsoWhenTTag(_),_) | (_,Ast0.IsoWhenTTag(_))
+ | (Ast0.IsoWhenFTag(_),_) | (_,Ast0.IsoWhenFTag(_)) ->
failwith "only within iso phase"
| _ -> false
let whencode = function
Ast0.WhenNot sd -> contextify_all.V0.combiner_statement_dots sd
| Ast0.WhenAlways s -> contextify_all.V0.combiner_statement s
- | Ast0.WhenModifier(_) -> () in
+ | Ast0.WhenModifier(_) -> ()
+ | Ast0.WhenNotTrue(e) -> contextify_all.V0.combiner_expression e
+ | Ast0.WhenNotFalse(e) -> contextify_all.V0.combiner_expression e in
let statement r k (s : Ast0.statement) =
k s;
let orify_rule_elem_ty = generic_orify_rule_elem disjty
let orify_rule_elem_param = generic_orify_rule_elem disjparam
let orify_rule_elem_decl = generic_orify_rule_elem disjdecl
+let orify_rule_elem_ini = generic_orify_rule_elem disjini
let disj_rule_elem r k re =
match Ast.unwrap re with
orify_rule_elem re exp (function exp -> Ast.rewrap exp (Ast.TopExp(exp)))
| Ast.Ty(ty) ->
orify_rule_elem_ty re ty (function ty -> Ast.rewrap ty (Ast.Ty(ty)))
+ | Ast.TopInit(init) ->
+ orify_rule_elem_ini re init
+ (function init -> Ast.rewrap init (Ast.TopInit(init)))
| Ast.Include(inc,s) -> re
| Ast.DefineHeader(def,id,params) -> re
| Ast.Default(def,colon) -> re
(* create an index for each constructor *)
-(* current max is 145 *)
+(* current max is 146 *)
(* doesn't really work - requires that identical terms with no token
subterms (eg dots) not appear on the same line *)
| Ast0.Exp(exp) -> [83]
| Ast0.TopExp(exp) -> [141]
| Ast0.Ty(ty) -> [124]
+ | Ast0.TopInit(init) -> [146]
| Ast0.Dots(d,whencode) -> [84]
| Ast0.Circles(d,whencode) -> [85]
| Ast0.Stars(d,whencode) -> [86]
| Ast0.CaseLineTag(d) -> Ast0.get_index d
| Ast0.TopTag(d) -> Ast0.get_index d
| Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
| Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
in
Hashtbl.add root_token_table key tokens)
(Ast0.get_index e,
(collect_minus_join_points e).V0.combiner_top_level e)
| Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
| Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
context_nodes
Ast0.Exp(exp) -> r.V0.combiner_expression exp
| Ast0.TopExp(exp) -> r.V0.combiner_expression exp
| Ast0.Ty(ty) -> r.V0.combiner_typeC ty
+ | Ast0.TopInit(init) -> r.V0.combiner_initialiser init
| Ast0.Decl(_,decl) -> r.V0.combiner_declaration decl
| _ -> do_nothing mk_statement r k e in
(Ast0.get_index e,
(collect_plus_nodes e).V0.combiner_top_level e)
| Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
+ | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
| Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
context_nodes
let into_end = intoinfo.Ast0.tline_end in
let into_left_offset = intoinfo.Ast0.left_offset in
let into_right_offset = intoinfo.Ast0.right_offset in
- Printf.printf "thing start %d thing end %d into start %d into end %d\n"
- thing_start thing_end into_start into_end;
if thing_end < into_start && thing_start < into_start
then (thing@into,
{{intoinfo with Ast0.tline_start = thing_start}
Printf.printf "thing offset %d left offset %d right offset %d\n"
thing_offset into_left_offset into_right_offset;
Pretty_print_cocci.print_anything "" thing;
+ Pretty_print_cocci.print_anything "" into;
failwith "can't figure out where to put the + code"
end
| (Ast0.TopTag(d1),Ast0.TopTag(d2)) ->
(strip_info.V0.rebuilder_top_level d1) =
(strip_info.V0.rebuilder_top_level d2)
+ | (Ast0.IsoWhenTTag(_),_) | (_,Ast0.IsoWhenTTag(_)) ->
+ failwith "only for isos within iso phase"
+ | (Ast0.IsoWhenFTag(_),_) | (_,Ast0.IsoWhenFTag(_)) ->
+ failwith "only for isos within iso phase"
| (Ast0.IsoWhenTag(_),_) | (_,Ast0.IsoWhenTag(_)) ->
failwith "only for isos within iso phase"
| _ -> false
| (Ast0.Exp(expa),Ast0.Exp(expb)) -> match_expr expa expb
| (Ast0.TopExp(expa),Ast0.TopExp(expb)) -> match_expr expa expb
| (Ast0.Exp(expa),Ast0.TopExp(expb)) -> match_expr expa expb
+ | (Ast0.TopInit(inita),Ast0.TopInit(initb)) -> match_init inita initb
| (Ast0.Ty(tya),Ast0.Ty(tyb)) -> match_typeC tya tyb
| (Ast0.Dots(d,[]),Ast0.Dots(d1,wc))
| (Ast0.Circles(d,[]),Ast0.Circles(d1,wc))
| Ast0.WhenAlways wc ->
conjunct_bindings prev
(add_multi_dot_binding d (Ast0.StmtTag wc))
+ | Ast0.WhenNotTrue wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.IsoWhenTTag wc))
+ | Ast0.WhenNotFalse wc ->
+ conjunct_bindings prev
+ (add_multi_dot_binding d
+ (Ast0.IsoWhenFTag wc))
| Ast0.WhenModifier(x) ->
conjunct_bindings prev
(add_multi_dot_binding d
failwith "metaparamlist not supported"
| _ -> e in
+ let whenfn (_,v) =
+ match v with
+ Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
+ | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
+ | Ast0.IsoWhenTTag(stm) -> Ast0.WhenNotTrue stm
+ | Ast0.IsoWhenFTag(stm) -> Ast0.WhenNotFalse stm
+ | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
+ | _ -> failwith "unexpected binding" in
+
let stmtfn r k e =
let e = k e in
match Ast0.unwrap e with
Ast0.rewrap e
(Ast0.Dots
(d,
- List.map
- (function (_,v) ->
- match v with
- Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
- | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
- | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
- | _ -> failwith "unexpected binding")
+ List.map whenfn
(List.filter (function (x,v) -> x = (dot_term d)) bindings)))
| Ast0.Circles(d,_) ->
Ast0.rewrap e
(Ast0.Circles
(d,
- List.map
- (function (_,v) ->
- match v with
- Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
- | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
- | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
- | _ -> failwith "unexpected binding")
+ List.map whenfn
(List.filter (function (x,v) -> x = (dot_term d)) bindings)))
| Ast0.Stars(d,_) ->
Ast0.rewrap e
(Ast0.Stars
(d,
- List.map
- (function (_,v) ->
- match v with
- Ast0.DotsStmtTag(stms) -> Ast0.WhenNot stms
- | Ast0.StmtTag(stm) -> Ast0.WhenAlways stm
- | Ast0.IsoWhenTag(x) -> Ast0.WhenModifier(x)
- | _ -> failwith "unexpected binding")
+ List.map whenfn
(List.filter (function (x,v) -> x = (dot_term d)) bindings)))
| _ -> e in
| Ast0.StmtTag(d) -> Ast0.StmtTag(rewrap.V0.rebuilder_statement d)
| Ast0.CaseLineTag(d) -> Ast0.CaseLineTag(rewrap.V0.rebuilder_case_line d)
| Ast0.TopTag(d) -> Ast0.TopTag(rewrap.V0.rebuilder_top_level d)
- | Ast0.IsoWhenTag(_) -> failwith "only for isos within iso phase"
+ | Ast0.IsoWhenTag(_) | Ast0.IsoWhenTTag(_) | Ast0.IsoWhenFTag(_) ->
+ failwith "only for isos within iso phase"
| Ast0.MetaPosTag(p) -> Ast0.MetaPosTag(p)
(* --------------------------------------------------------------------- *)
| "exists" when in_rule_name -> check_context_linetype s; TExists
| "forall" when in_rule_name -> check_context_linetype s; TForall
| "reverse" when in_rule_name -> check_context_linetype s; TReverse
+ | "script" when in_rule_name -> check_context_linetype s; TScript
| "char" -> Tchar linetype
| "short" -> Tshort linetype
Ast.CocciRulename (Some n,d,i,a,e,ee)
| None -> Ast.CocciRulename (None,d,i,a,e,ee)
-let make_script_rule_name_result scr lang deps =
- let s = id2name scr in
+let make_script_rule_name_result lang deps =
let l = id2name lang in
- if s <> "script" then
- raise (Semantic_cocci.Semantic ("malformed script rule"));
- Ast.ScriptRulename (l,deps)
+ Ast.ScriptRulename (l,deps)
| PC.TArobArob -> "@@"
| PC.TArob -> "@"
| PC.TPArob -> "P@"
+ | PC.TScript -> "script"
| PC.TWhen(clt) -> "WHEN"^(line_type2c clt)
+ | PC.TWhenTrue(clt) -> "WHEN TRUE"^(line_type2c clt)
+ | PC.TWhenFalse(clt) -> "WHEN FALSE"^(line_type2c clt)
| PC.TAny(clt) -> "ANY"^(line_type2c clt)
| PC.TStrict(clt) -> "STRICT"^(line_type2c clt)
| PC.TEllipsis(clt) -> "..."^(line_type2c clt)
| PC.TCBrace(clt) -> "}"^(line_type2c clt)
| PC.TOCro(clt) -> "["^(line_type2c clt)
| PC.TCCro(clt) -> "]"^(line_type2c clt)
+ | PC.TOInit(clt) -> "{"^(line_type2c clt)
| PC.TPtrOp(clt) -> "->"^(line_type2c clt)
| PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
| PC.TMetaLocalFunc(_,_,_,clt)
- | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
+ | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
(* | PC.TCircles(clt) | PC.TStars(clt) *)
| PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
| PC.TCPar(clt)
| PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+ | PC.TOInit(clt)
| PC.TPtrOp(clt)
| PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
| PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
- | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt) |
+ PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
(* | PC.TCircles(clt) | PC.TStars(clt) *)
| PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
| PC.TCPar(clt)
| PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+ | PC.TOInit(clt)
| PC.TPtrOp(clt)
| PC.TMetaLocalFunc(a,b,c,_) -> (PC.TMetaLocalFunc(a,b,c,clt),x)
| PC.TWhen(_) -> (PC.TWhen(clt),x)
+ | PC.TWhenTrue(_) -> (PC.TWhenTrue(clt),x)
+ | PC.TWhenFalse(_) -> (PC.TWhenFalse(clt),x)
| PC.TAny(_) -> (PC.TAny(clt),x)
| PC.TStrict(_) -> (PC.TStrict(clt),x)
| PC.TEllipsis(_) -> (PC.TEllipsis(clt),x)
| PC.TCBrace(_) -> (PC.TCBrace(clt),x)
| PC.TOCro(_) -> (PC.TOCro(clt),x)
| PC.TCCro(_) -> (PC.TCCro(clt),x)
+ | PC.TOInit(_) -> (PC.TOInit(clt),x)
| PC.TPtrOp(_) -> (PC.TPtrOp(clt),x)
| PC.TMetaStm(_,_,clt) | PC.TMetaStmList(_,_,clt) | PC.TMetaErr(_,_,_,clt)
| PC.TMetaFunc(_,_,_,clt) | PC.TMetaLocalFunc(_,_,_,clt)
| PC.TMetaDeclarer(_,_,_,clt) | PC.TMetaIterator(_,_,_,clt) -> split t clt
- | PC.TMPtVirg | PC.TArob | PC.TArobArob -> ([t],[t])
+ | PC.TMPtVirg | PC.TArob | PC.TArobArob | PC.TScript -> ([t],[t])
| PC.TPArob | PC.TMetaPos(_,_,_,_) -> ([t],[])
| PC.TFunDecl(clt)
- | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TLineEnd(clt)
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
+ | PC.TAny(clt) | PC.TStrict(clt) | PC.TLineEnd(clt)
| PC.TEllipsis(clt) (* | PC.TCircles(clt) | PC.TStars(clt) *) -> split t clt
| PC.TOEllipsis(_) | PC.TCEllipsis(_) (* clt must be context *)
| PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
| PC.TDmOp(_,clt) | PC.TTilde (clt) -> split t clt
- | PC.TOBrace(clt) | PC.TCBrace(clt) -> split t clt
+ | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOInit(clt) -> split t clt
| PC.TOCro(clt) | PC.TCCro(clt) -> split t clt
| PC.TPtrOp(clt) -> split t clt
(PC.TOEllipsis(_),_) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
| (PC.TPOEllipsis(_),_) (* | (PC.TOCircles(_),_) | (PC.TOStars(_),_) *)
| (PC.TEllipsis(_),_) (* | (PC.TCircles(_),_) | (PC.TStars(_),_) *)
- | (PC.TPtVirg(_),_) | (PC.TOBrace(_),_) | (PC.TCBrace(_),_)
+ | (PC.TPtVirg(_),_) | (PC.TOBrace(_),_) | (PC.TOInit(_),_)
+ | (PC.TCBrace(_),_)
| (PC.TPure,_) | (PC.TContext,_)
| (PC.Tstatic(_),_) | (PC.Textern(_),_)
| (PC.Tinline(_),_) | (PC.Ttypedef(_),_) | (PC.Tattr(_),_) -> true
| PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
| PC.TFunDecl(clt)
- | PC.TWhen(clt) | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
+ | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
+ | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
(* | PC.TCircles(clt) | PC.TStars(clt) *)
| PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
| PC.TCPar0(clt)
| PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt)
+ | PC.TOInit(clt)
| PC.TPtrOp(clt)
| x::xs when token2line x = line -> x :: (find_line_end inwhen line clt q xs)
| xs -> (PC.TLineEnd(clt),q)::(insert_line_end xs)
+let rec translate_when_true_false = function
+ [] -> []
+ | (PC.TWhen(clt),q)::((PC.TNotEq(_),_) as x)::(PC.TIdent("true",_),_)::xs ->
+ (PC.TWhenTrue(clt),q)::x::xs
+ | (PC.TWhen(clt),q)::((PC.TNotEq(_),_) as x)::(PC.TIdent("false",_),_)::xs ->
+ (PC.TWhenFalse(clt),q)::x::xs
+ | x::xs -> x :: (translate_when_true_false xs)
+
+(* ----------------------------------------------------------------------- *)
+(* top level initializers: a sequence of braces followed by a dot *)
+
+let find_top_init tokens =
+ match tokens with
+ (PC.TOBrace(clt),q) :: rest ->
+ let rec dot_start acc = function
+ ((PC.TOBrace(_),_) as x) :: rest ->
+ dot_start (x::acc) rest
+ | ((PC.TDot(_),_) :: rest) as x ->
+ Some ((PC.TOInit(clt),q) :: (List.rev acc) @ x)
+ | l -> None in
+ let rec comma_end acc = function
+ ((PC.TCBrace(_),_) as x) :: rest ->
+ comma_end (x::acc) rest
+ | ((PC.TComma(_),_) :: rest) as x ->
+ Some ((PC.TOInit(clt),q) :: (List.rev x) @ acc)
+ | l -> None in
+ (match dot_start [] rest with
+ Some x -> x
+ | None ->
+ (match List.rev rest with
+ ((PC.EOF,_) as x)::rest ->
+ (match comma_end [x] rest with
+ Some x -> x
+ | None -> tokens)
+ | _ -> failwith "unexpected empty token list"))
+ | _ -> tokens
+
(* ----------------------------------------------------------------------- *)
(* process pragmas: they can only be used in + code, and adjacent to
another + token. They are concatenated to the string representation of
| e -> raise e
let prepare_tokens tokens =
- insert_line_end
- (detect_types false (find_function_names (detect_attr tokens)))
+ find_top_init
+ (translate_when_true_false (* after insert_line_end *)
+ (insert_line_end
+ (detect_types false (find_function_names (detect_attr tokens)))))
let rec consume_minus_positions = function
[] -> []
(Data.clt)
# 138 "parser_cocci_menhir.ml"
)
- | TWhen of (
+ | TWhenTrue of (
# 73 "parser_cocci_menhir.mly"
(Data.clt)
# 143 "parser_cocci_menhir.ml"
+)
+ | TWhenFalse of (
+# 73 "parser_cocci_menhir.mly"
+ (Data.clt)
+# 148 "parser_cocci_menhir.ml"
+)
+ | TWhen of (
+# 73 "parser_cocci_menhir.mly"
+ (Data.clt)
+# 153 "parser_cocci_menhir.ml"
)
| TUsing
| TTypedef
| TTypeId of (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 150 "parser_cocci_menhir.ml"
+# 160 "parser_cocci_menhir.ml"
)
| TType
| TTilde of (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 156 "parser_cocci_menhir.ml"
+# 166 "parser_cocci_menhir.ml"
)
| TSwitch of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 161 "parser_cocci_menhir.ml"
+# 171 "parser_cocci_menhir.ml"
)
| TString of (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 166 "parser_cocci_menhir.ml"
+# 176 "parser_cocci_menhir.ml"
)
| TStrict of (
# 73 "parser_cocci_menhir.mly"
(Data.clt)
-# 171 "parser_cocci_menhir.ml"
+# 181 "parser_cocci_menhir.ml"
)
| TStatement
| TSizeof of (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 177 "parser_cocci_menhir.ml"
+# 187 "parser_cocci_menhir.ml"
)
| TShOp of (
# 95 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 182 "parser_cocci_menhir.ml"
+# 192 "parser_cocci_menhir.ml"
)
| TScriptData of (
# 70 "parser_cocci_menhir.mly"
(string)
-# 187 "parser_cocci_menhir.ml"
+# 197 "parser_cocci_menhir.ml"
)
+ | TScript
| TRuleName of (
# 47 "parser_cocci_menhir.mly"
(string)
-# 192 "parser_cocci_menhir.ml"
+# 203 "parser_cocci_menhir.ml"
)
| TRightIso
| TReverse
| TReturn of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 199 "parser_cocci_menhir.ml"
+# 210 "parser_cocci_menhir.ml"
)
| TPure
| TPtrOp of (
# 103 "parser_cocci_menhir.mly"
(Data.clt)
-# 205 "parser_cocci_menhir.ml"
+# 216 "parser_cocci_menhir.ml"
)
| TPtVirg of (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 210 "parser_cocci_menhir.ml"
+# 221 "parser_cocci_menhir.ml"
)
| TPragma of (
# 78 "parser_cocci_menhir.mly"
(string)
-# 215 "parser_cocci_menhir.ml"
+# 226 "parser_cocci_menhir.ml"
)
| TPosition
| TPosAny
| TPlusFile of (
# 82 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 222 "parser_cocci_menhir.ml"
+# 233 "parser_cocci_menhir.ml"
)
| TPlus0
| TPlus of (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 228 "parser_cocci_menhir.ml"
+# 239 "parser_cocci_menhir.ml"
)
| TPathIsoFile of (
# 78 "parser_cocci_menhir.mly"
(string)
-# 233 "parser_cocci_menhir.ml"
+# 244 "parser_cocci_menhir.ml"
)
| TParameter
| TPOEllipsis of (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 239 "parser_cocci_menhir.ml"
+# 250 "parser_cocci_menhir.ml"
)
| TPCEllipsis of (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 244 "parser_cocci_menhir.ml"
+# 255 "parser_cocci_menhir.ml"
)
| TPArob
| TOrLog of (
# 88 "parser_cocci_menhir.mly"
(Data.clt)
-# 250 "parser_cocci_menhir.ml"
+# 261 "parser_cocci_menhir.ml"
)
| TOr of (
# 90 "parser_cocci_menhir.mly"
(Data.clt)
-# 255 "parser_cocci_menhir.ml"
+# 266 "parser_cocci_menhir.ml"
)
| TOn
| TOPar0 of (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 261 "parser_cocci_menhir.ml"
+# 272 "parser_cocci_menhir.ml"
)
| TOPar of (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 266 "parser_cocci_menhir.ml"
+# 277 "parser_cocci_menhir.ml"
+)
+ | TOInit of (
+# 100 "parser_cocci_menhir.mly"
+ (Data.clt)
+# 282 "parser_cocci_menhir.ml"
)
| TOEllipsis of (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 271 "parser_cocci_menhir.ml"
+# 287 "parser_cocci_menhir.ml"
)
| TOCro of (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 276 "parser_cocci_menhir.ml"
+# 292 "parser_cocci_menhir.ml"
)
| TOBrace of (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 281 "parser_cocci_menhir.ml"
+# 297 "parser_cocci_menhir.ml"
)
| TNothing
| TNotEq of (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 287 "parser_cocci_menhir.ml"
+# 303 "parser_cocci_menhir.ml"
)
| TNever
| TName
| TMul of (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 294 "parser_cocci_menhir.ml"
+# 310 "parser_cocci_menhir.ml"
)
| TMinusFile of (
# 82 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 299 "parser_cocci_menhir.ml"
+# 315 "parser_cocci_menhir.ml"
)
| TMinus of (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 304 "parser_cocci_menhir.ml"
+# 320 "parser_cocci_menhir.ml"
)
| TMid0 of (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 309 "parser_cocci_menhir.ml"
+# 325 "parser_cocci_menhir.ml"
)
| TMetaType of (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 314 "parser_cocci_menhir.ml"
+# 330 "parser_cocci_menhir.ml"
)
| TMetaStmList of (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 319 "parser_cocci_menhir.ml"
+# 335 "parser_cocci_menhir.ml"
)
| TMetaStm of (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 324 "parser_cocci_menhir.ml"
+# 340 "parser_cocci_menhir.ml"
)
| TMetaPos of (
# 67 "parser_cocci_menhir.mly"
(Parse_aux.pos_info)
-# 329 "parser_cocci_menhir.ml"
+# 345 "parser_cocci_menhir.ml"
)
| TMetaParamList of (
# 65 "parser_cocci_menhir.mly"
(Parse_aux.list_info)
-# 334 "parser_cocci_menhir.ml"
+# 350 "parser_cocci_menhir.ml"
)
| TMetaParam of (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 339 "parser_cocci_menhir.ml"
+# 355 "parser_cocci_menhir.ml"
)
| TMetaLocalIdExp of (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 344 "parser_cocci_menhir.ml"
+# 360 "parser_cocci_menhir.ml"
)
| TMetaLocalFunc of (
# 61 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 349 "parser_cocci_menhir.ml"
+# 365 "parser_cocci_menhir.ml"
)
| TMetaIterator of (
# 62 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 354 "parser_cocci_menhir.ml"
+# 370 "parser_cocci_menhir.ml"
)
| TMetaIdExp of (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 359 "parser_cocci_menhir.ml"
+# 375 "parser_cocci_menhir.ml"
)
| TMetaId of (
# 61 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 364 "parser_cocci_menhir.ml"
+# 380 "parser_cocci_menhir.ml"
)
| TMetaFunc of (
# 61 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 369 "parser_cocci_menhir.ml"
+# 385 "parser_cocci_menhir.ml"
)
| TMetaExpList of (
# 65 "parser_cocci_menhir.mly"
(Parse_aux.list_info)
-# 374 "parser_cocci_menhir.ml"
+# 390 "parser_cocci_menhir.ml"
)
| TMetaExp of (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 379 "parser_cocci_menhir.ml"
+# 395 "parser_cocci_menhir.ml"
)
| TMetaErr of (
# 63 "parser_cocci_menhir.mly"
(Parse_aux.expinfo)
-# 384 "parser_cocci_menhir.ml"
+# 400 "parser_cocci_menhir.ml"
)
| TMetaDeclarer of (
# 62 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 389 "parser_cocci_menhir.ml"
+# 405 "parser_cocci_menhir.ml"
)
| TMetaConst of (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 394 "parser_cocci_menhir.ml"
+# 410 "parser_cocci_menhir.ml"
)
| TMPtVirg
| TLogOp of (
# 94 "parser_cocci_menhir.mly"
(Ast_cocci.logicalOp * Data.clt)
-# 400 "parser_cocci_menhir.ml"
+# 416 "parser_cocci_menhir.ml"
)
| TLocal
| TLineEnd of (
# 73 "parser_cocci_menhir.mly"
(Data.clt)
-# 406 "parser_cocci_menhir.ml"
+# 422 "parser_cocci_menhir.ml"
)
| TIteratorId of (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 411 "parser_cocci_menhir.ml"
+# 427 "parser_cocci_menhir.ml"
)
| TIterator
| TIsoType
| TInt of (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 426 "parser_cocci_menhir.ml"
+# 442 "parser_cocci_menhir.ml"
)
| TIncludeNL of (
# 79 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 431 "parser_cocci_menhir.ml"
+# 447 "parser_cocci_menhir.ml"
)
| TIncludeL of (
# 79 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 436 "parser_cocci_menhir.ml"
+# 452 "parser_cocci_menhir.ml"
)
| TInc of (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 441 "parser_cocci_menhir.ml"
+# 457 "parser_cocci_menhir.ml"
)
| TIf of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 446 "parser_cocci_menhir.ml"
+# 462 "parser_cocci_menhir.ml"
)
| TIdentifier
| TIdent of (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 452 "parser_cocci_menhir.ml"
+# 468 "parser_cocci_menhir.ml"
)
| TIdExpression
| TGoto of (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 458 "parser_cocci_menhir.ml"
+# 474 "parser_cocci_menhir.ml"
)
| TFunction
| TFunDecl of (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 464 "parser_cocci_menhir.ml"
+# 480 "parser_cocci_menhir.ml"
)
| TFresh
| TForall
| TFor of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 471 "parser_cocci_menhir.ml"
+# 487 "parser_cocci_menhir.ml"
)
| TFloat of (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 476 "parser_cocci_menhir.ml"
+# 492 "parser_cocci_menhir.ml"
)
| TExtends
| TExpression
| TEqEq of (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 486 "parser_cocci_menhir.ml"
+# 502 "parser_cocci_menhir.ml"
)
| TEq of (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 491 "parser_cocci_menhir.ml"
+# 507 "parser_cocci_menhir.ml"
)
| TElse of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 496 "parser_cocci_menhir.ml"
+# 512 "parser_cocci_menhir.ml"
)
| TEllipsis of (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 501 "parser_cocci_menhir.ml"
+# 517 "parser_cocci_menhir.ml"
)
| TDotDot of (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 506 "parser_cocci_menhir.ml"
+# 522 "parser_cocci_menhir.ml"
)
| TDot of (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 511 "parser_cocci_menhir.ml"
+# 527 "parser_cocci_menhir.ml"
)
| TDo of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 516 "parser_cocci_menhir.ml"
+# 532 "parser_cocci_menhir.ml"
)
| TDmOp of (
# 96 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 521 "parser_cocci_menhir.ml"
+# 537 "parser_cocci_menhir.ml"
)
| TDisable
| TDepends
| TDefineParam of (
# 81 "parser_cocci_menhir.mly"
(Data.clt * token * int)
-# 528 "parser_cocci_menhir.ml"
+# 544 "parser_cocci_menhir.ml"
)
| TDefine of (
# 80 "parser_cocci_menhir.mly"
(Data.clt * token)
-# 533 "parser_cocci_menhir.ml"
+# 549 "parser_cocci_menhir.ml"
)
| TDefault of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 538 "parser_cocci_menhir.ml"
+# 554 "parser_cocci_menhir.ml"
)
| TDeclarerId of (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 543 "parser_cocci_menhir.ml"
+# 559 "parser_cocci_menhir.ml"
)
| TDeclarer
| TDec of (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 549 "parser_cocci_menhir.ml"
+# 565 "parser_cocci_menhir.ml"
)
| TContinue of (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 554 "parser_cocci_menhir.ml"
+# 570 "parser_cocci_menhir.ml"
)
| TContext
| TConstant
| TComma of (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 561 "parser_cocci_menhir.ml"
+# 577 "parser_cocci_menhir.ml"
)
| TChar of (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 566 "parser_cocci_menhir.ml"
+# 582 "parser_cocci_menhir.ml"
)
| TCase of (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 571 "parser_cocci_menhir.ml"
+# 587 "parser_cocci_menhir.ml"
)
| TCPar0 of (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 576 "parser_cocci_menhir.ml"
+# 592 "parser_cocci_menhir.ml"
)
| TCPar of (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 581 "parser_cocci_menhir.ml"
+# 597 "parser_cocci_menhir.ml"
)
| TCEllipsis of (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 586 "parser_cocci_menhir.ml"
+# 602 "parser_cocci_menhir.ml"
)
| TCCro of (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 591 "parser_cocci_menhir.ml"
+# 607 "parser_cocci_menhir.ml"
)
| TCBrace of (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 596 "parser_cocci_menhir.ml"
+# 612 "parser_cocci_menhir.ml"
)
| TBreak of (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 601 "parser_cocci_menhir.ml"
+# 617 "parser_cocci_menhir.ml"
)
| TBang0
| TBang of (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 607 "parser_cocci_menhir.ml"
+# 623 "parser_cocci_menhir.ml"
)
| TAssign of (
# 107 "parser_cocci_menhir.mly"
(Ast_cocci.assignOp * Data.clt)
-# 612 "parser_cocci_menhir.ml"
+# 628 "parser_cocci_menhir.ml"
)
| TArobArob
| TArob
| TAny of (
# 73 "parser_cocci_menhir.mly"
(Data.clt)
-# 619 "parser_cocci_menhir.ml"
+# 635 "parser_cocci_menhir.ml"
)
| TAndLog of (
# 89 "parser_cocci_menhir.mly"
(Data.clt)
-# 624 "parser_cocci_menhir.ml"
+# 640 "parser_cocci_menhir.ml"
)
| TAnd of (
# 92 "parser_cocci_menhir.mly"
(Data.clt)
-# 629 "parser_cocci_menhir.ml"
+# 645 "parser_cocci_menhir.ml"
)
| EOF
fun _tok ->
match _tok with
| EOF ->
- 162
+ 166
| TAnd _ ->
- 161
+ 165
| TAndLog _ ->
- 160
+ 164
| TAny _ ->
- 159
+ 163
| TArob ->
- 158
+ 162
| TArobArob ->
- 157
+ 161
| TAssign _ ->
- 156
+ 160
| TBang _ ->
- 155
+ 159
| TBang0 ->
- 154
+ 158
| TBreak _ ->
- 153
+ 157
| TCBrace _ ->
- 152
+ 156
| TCCro _ ->
- 151
+ 155
| TCEllipsis _ ->
- 150
+ 154
| TCPar _ ->
- 149
+ 153
| TCPar0 _ ->
- 148
+ 152
| TCase _ ->
- 147
+ 151
| TChar _ ->
- 146
+ 150
| TComma _ ->
- 145
+ 149
| TConstant ->
- 144
+ 148
| TContext ->
- 143
+ 147
| TContinue _ ->
- 142
+ 146
| TDec _ ->
- 141
+ 145
| TDeclarer ->
- 140
+ 144
| TDeclarerId _ ->
- 139
+ 143
| TDefault _ ->
- 138
+ 142
| TDefine _ ->
- 137
+ 141
| TDefineParam _ ->
- 136
+ 140
| TDepends ->
- 135
+ 139
| TDisable ->
- 134
+ 138
| TDmOp _ ->
- 133
+ 137
| TDo _ ->
- 132
+ 136
| TDot _ ->
- 131
+ 135
| TDotDot _ ->
- 130
+ 134
| TEllipsis _ ->
- 129
+ 133
| TElse _ ->
- 128
+ 132
| TEq _ ->
- 127
+ 131
| TEqEq _ ->
- 126
+ 130
| TError ->
- 125
+ 129
| TEver ->
- 124
+ 128
| TExists ->
- 123
+ 127
| TExpression ->
- 122
+ 126
| TExtends ->
- 121
+ 125
| TFloat _ ->
- 120
+ 124
| TFor _ ->
- 119
+ 123
| TForall ->
- 118
+ 122
| TFresh ->
- 117
+ 121
| TFunDecl _ ->
- 116
+ 120
| TFunction ->
- 115
+ 119
| TGoto _ ->
- 114
+ 118
| TIdExpression ->
- 113
+ 117
| TIdent _ ->
- 112
+ 116
| TIdentifier ->
- 111
+ 115
| TIf _ ->
- 110
+ 114
| TInc _ ->
- 109
+ 113
| TIncludeL _ ->
- 108
+ 112
| TIncludeNL _ ->
- 107
+ 111
| TInt _ ->
- 106
+ 110
| TInvalid ->
- 105
+ 109
| TIso ->
- 104
+ 108
| TIsoArgExpression ->
- 103
+ 107
| TIsoDeclaration ->
- 102
+ 106
| TIsoExpression ->
- 101
+ 105
| TIsoStatement ->
- 100
+ 104
| TIsoTestExpression ->
- 99
+ 103
| TIsoTopLevel ->
- 98
+ 102
| TIsoType ->
- 97
+ 101
| TIterator ->
- 96
+ 100
| TIteratorId _ ->
- 95
+ 99
| TLineEnd _ ->
- 94
+ 98
| TLocal ->
- 93
+ 97
| TLogOp _ ->
- 92
+ 96
| TMPtVirg ->
- 91
+ 95
| TMetaConst _ ->
- 90
+ 94
| TMetaDeclarer _ ->
- 89
+ 93
| TMetaErr _ ->
- 88
+ 92
| TMetaExp _ ->
- 87
+ 91
| TMetaExpList _ ->
- 86
+ 90
| TMetaFunc _ ->
- 85
+ 89
| TMetaId _ ->
- 84
+ 88
| TMetaIdExp _ ->
- 83
+ 87
| TMetaIterator _ ->
- 82
+ 86
| TMetaLocalFunc _ ->
- 81
+ 85
| TMetaLocalIdExp _ ->
- 80
+ 84
| TMetaParam _ ->
- 79
+ 83
| TMetaParamList _ ->
- 78
+ 82
| TMetaPos _ ->
- 77
+ 81
| TMetaStm _ ->
- 76
+ 80
| TMetaStmList _ ->
- 75
+ 79
| TMetaType _ ->
- 74
+ 78
| TMid0 _ ->
- 73
+ 77
| TMinus _ ->
- 72
+ 76
| TMinusFile _ ->
- 71
+ 75
| TMul _ ->
- 70
+ 74
| TName ->
- 69
+ 73
| TNever ->
- 68
+ 72
| TNotEq _ ->
- 67
+ 71
| TNothing ->
- 66
+ 70
| TOBrace _ ->
- 65
+ 69
| TOCro _ ->
- 64
+ 68
| TOEllipsis _ ->
- 63
+ 67
+ | TOInit _ ->
+ 66
| TOPar _ ->
- 62
+ 65
| TOPar0 _ ->
- 61
+ 64
| TOn ->
- 60
+ 63
| TOr _ ->
- 59
+ 62
| TOrLog _ ->
- 58
+ 61
| TPArob ->
- 57
+ 60
| TPCEllipsis _ ->
- 56
+ 59
| TPOEllipsis _ ->
- 55
+ 58
| TParameter ->
- 54
+ 57
| TPathIsoFile _ ->
- 53
+ 56
| TPlus _ ->
- 52
+ 55
| TPlus0 ->
- 51
+ 54
| TPlusFile _ ->
- 50
+ 53
| TPosAny ->
- 49
+ 52
| TPosition ->
- 48
+ 51
| TPragma _ ->
- 47
+ 50
| TPtVirg _ ->
- 46
+ 49
| TPtrOp _ ->
- 45
+ 48
| TPure ->
- 44
+ 47
| TReturn _ ->
- 43
+ 46
| TReverse ->
- 42
+ 45
| TRightIso ->
- 41
+ 44
| TRuleName _ ->
- 40
+ 43
+ | TScript ->
+ 42
| TScriptData _ ->
- 39
+ 41
| TShOp _ ->
- 38
+ 40
| TSizeof _ ->
- 37
+ 39
| TStatement ->
- 36
+ 38
| TStrict _ ->
- 35
+ 37
| TString _ ->
- 34
+ 36
| TSwitch _ ->
- 33
+ 35
| TTilde _ ->
- 32
+ 34
| TType ->
- 31
+ 33
| TTypeId _ ->
- 30
+ 32
| TTypedef ->
- 29
+ 31
| TUsing ->
- 28
+ 30
| TWhen _ ->
+ 29
+ | TWhenFalse _ ->
+ 28
+ | TWhenTrue _ ->
27
| TWhile _ ->
26
Obj.repr _v
| TOEllipsis _v ->
Obj.repr _v
+ | TOInit _v ->
+ Obj.repr _v
| TOPar _v ->
Obj.repr _v
| TOPar0 _v ->
Obj.repr ()
| TRuleName _v ->
Obj.repr _v
+ | TScript ->
+ Obj.repr ()
| TScriptData _v ->
Obj.repr _v
| TShOp _v ->
Obj.repr ()
| TWhen _v ->
Obj.repr _v
+ | TWhenFalse _v ->
+ Obj.repr _v
+ | TWhenTrue _v ->
+ Obj.repr _v
| TWhile _v ->
Obj.repr _v
| TWhy _v ->
Obj.repr _v
let default_reduction =
- (16, "\000\000\000\000\001 \001!\000\000\001#\001\"\000\001\000\000\001[\000\000\000\000\000\136\000\000\000\000\001\213\000\142\000\145\002\195\002\194\000\146\001\013\001\019\001\015\001\018\001\017\000\135\001\011\001\026\000\000\000\000\001\025\000\000\000\000\000\000\000\000\000\000\001O\000\232\002\185\002o\000\000\000\000\000\000\000\000\000\000\002\190\000\000\001\022\000\000\002\192\000\000\001\029\001\028\000\000\000\000\002\249\0029\000\000\002\247\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\252\000\000\002S\000\000\000\000\002\246\002\248\002?\001\004\002>\001\002\001\003\002=\002<\002;\0027\000\000\000\000\0028\000\205\000\000\002:\000\000\002\245\000\000\002\220\001\001\002\026\000\000\000\000\002\029\000\000\000\015\000\000\000\000\000\000\000\000\000\206\0026\002B\000[\000\021\000]\000\000\000\000\000c\000\000\000\000\000\000\000\000\000\000\000\000\000\022\000\000\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\001\250\000R\000\215\000^\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\000T\000\000\000S\000\000\000\000\000\140\000\216\000\000\002 \000\217\000\014\000\000\001\014\001\020\001\016\001\012\000\016\000\000\000\000\000\143\000\000\000\141\000\000\000\000\000\220\000\000\000\000\002\027\002\030\000\000\002\028\002\031\002\221\002\219\000\000\002@\002\218\000\000\002[\000\000\000\000\001\189\000\000\001i\001\171\000\000\000\000\002Z\000\000\002\237\002Y\002X\002W\002V\002U\002Q\000\000\000\000\002R\000\000\002T\000\000\000\000\002\234\002(\000\000\000\000\002+\000\000\000\000\002.\000\000\000\000\002)\002,\000\000\002*\002-\002\\\002P\002\235\002\233\002\232\002\236\000\000\000\000\000\000\000g\000h\000\000\000\000\000W\000\000\000V\000\227\000\000\001\205\000\000\000\000\000\000\000\000\000\000\000\210\001\211\000\000\000\000\001s\000U\0001\000\203\000_\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\000\000\0003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002A\000\000\000\144\000\000\000\000\001\188\000\000\001g\001\170\000\000\000\000\000d\000\000\002\252\000\000\000\000\001\206\000\000\000\000\002\223\002\222\000\000\000Q\000\147\000\000\001Q\000\000\002\188\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\225\000\151\000\000\000\000\000n\000o\001\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\160\001\194\000\000\000\148\000\155\000\000\001\196\000\000\000\000\000\000\000\000\000\149\000\161\000\000\001W\000\000\000\000\002\187\000\000\000\000\000\138\000\000\000\000\002\186\000\000\000\000\000\000\002\189\002\193\000\000\000\000\000\000\001\023\000\000\000\214\000\000\001\024\000\000\000\000\001:\000\000\0019\000\000\001G\000\000\001]\000\000\000\000\000\000\000\000\000\000\000\000\001\008\000\000\000\000\002\216\000\000\000\189\002\215\002\181\002\183\002\184\002\182\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002`\000\000\000\000\000\000\000\000\002g\000\000\000\000\002f\002e\002d\002c\002b\0016\002^\000\000\000\000\002_\000\000\002a\000\000\000\000\002\241\002/\000\000\000\000\0022\000\000\000\000\0025\000\000\000\000\0020\0023\000\000\0021\0024\002i\002]\002\242\002\240\002\239\000i\000j\000\000\000\000\000Z\000\000\000Y\000\000\002h\000\000\001\172\000X\000?\000\226\000`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\244\002\243\000\000\002\172\000\000\002\171\000\000\000\000\000\018\000\000\000\000\000\000\002\253\000\000\001u\000\000\000\000\000\000\000\162\002\162\001M\000\000\000\153\001L\001%\001$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\207\000\208\000\195\000\000\001Y\000\000\000\000\000\194\000\190\000\000\000\197\000\191\000\196\000\000\002\174\000\000\002\173\002\159\000\000\000\000\000\000\000\000\000\000\002\168\000\000\000\000\000\000\000\000\000\000\002\169\002\161\000\000\002\175\000\000\002\163\000\000\000\166\000\000\002\178\000\152\000\000\001'\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000\000\000w\000\000\000\000\000\000\002F\000\000\000\000\000\000\002N\000\000\000\000\002M\000\000\002\230\002L\002K\002J\002I\002H\002D\000\000\000\000\002E\000\000\002G\000\000\000\000\002\227\002!\000\000\000\000\002$\000\000\000\000\002'\000\000\000\000\002\"\002%\000\000\002#\002&\002O\002C\002\228\002\226\002\225\002\229\000\000\000\000\000\000\000e\000f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\212\001(\000\000\000\000\000\000\001.\000\000\000\000\001/\000#\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001-\0012\000\000\001,\000\000\000\000\0014\000\000\000\000\000\000\000\000\000\000\000\000\000t\000q\000r\0015\0011\000\000\000\000\0010\001*\000\000\001)\000\000\000\182\000\000\002\140\000\000\000\000\000\178\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\185\000\000\000\000\000\188\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\007\000\000\000\000\000\000\000\175\000\000\000\172\000\000\000\000\000\000\000\000\000\000\000\183\000\000\000\179\000\000\000\000\002\198\000\000\002\205\000\168\000\000\000\000\000\000\000\000\000\180\000\000\000\176\000\173\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\184\000\000\000\000\000\187\000\000\002\199\000\167\000\000\002\200\000\000\002\207\000\000\000\000\000\000\000\000\000\186\000\000\000\170\000\000\000\000\000\000\000\000\001\006\000\000\000\000\000\000\000\174\000\000\000\171\000\000\000\000\000\000\000\000\000\000\000\181\000\000\000\177\000\164\000\163\000\000\002\208\002\209\000\000\002\210\000\000\002\211\000\000\001&\002\166\000\000\000\000\001\193\000\000\001q\001\176\000\000\002\160\000\000\000\000\000\000\002\165\000\000\000\000\000\000\000\250\000\000\000\244\000\000\000\245\000\000\000\255\000\243\000\254\000\000\002\177\001\000\000\000\000\169\000\000\000\000\000\000\000\000\000\252\000\247\001\190\000\000\000\248\000\000\000\249\000\000\001k\001\173\000\000\000\000\000\000\001\201\000\000\001\199\000\000\000\000\001\203\001\197\000\000\001\204\001\198\000\000\002\179\001\207\000\000\000\165\000\000\000\000\001\191\000\000\001m\001\174\000\000\002\254\000\000\002\250\000\000\002\251\000\019\000\020\000\000\000\000\002}\000\000\002|\000\000\000\000\002\127\000\000\002~\000\000\000\000\000\000\001\234\000\000\000\000\001\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\241\000\000\000\000\001\244\000\000\000\000\001\228\000\000\000\000\001\231\000\000\000\000\000\000\001\235\000\000\000\000\001\239\000\000\000\000\001\192\000\000\000\000\001\232\000\000\000\000\001\236\002z\001\229\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\240\000\000\000\000\001\243\000\000\002{\000\000\000\000\000\000\000\000\001\242\000\000\001\226\000\000\001\227\000\000\000\000\001\230\000\000\000\000\000\000\001\233\000\000\000\000\001\237\000\000\001o\001\175\000\000\002\128\000\000\000\000\000\000\002\255\000\017\000u\000\000\003\000\000\000\000\000\002\136\000\000\000\000\002\180\000a\000\000\000\000\000\000\000b\000\000\002\170\000\000\001S\002\167\000\000\000\000\001@\000\000\001?\000\000\001H\000\000\001c\000\000\000\000\000\000\001>\000\000\001=\000\000\001E\000\000\001a\000\000\000\000\000\000\001B\000\000\001A\000\000\001F\000\000\001e\000\000\000\000\000\000\001C\000\000\000\000\000\000\000\000\001<\000\000\001;\000\000\001I\000\000\001_\000\000\000\000\000\000\001D\000\002\000\000\000N\000O\000M\001J\000\003\000\000\000\000\002l\000\000\001\248\000\000\002r\002t\000\000\000\000\001\140\002s\000\128\000\000\000\000\002\158\000\000\000\000\000\000\000z\000\000\000\000\002\146\000\000\001\221\001\220\001\135\002x\002p\002q\000\000\001\167\000\000\002m\000\000\000\000\000|\000\000\000\000\002\150\000\000\001\149\000\000\000\000\001\146\000\000\000\000\000\000\001\148\000\000\001\147\000\000\000\000\000\000\000\000\000\000\000\000\001\168\000\000\001\144\000\000\001\143\000\000\000v\000\000\000\000\002\138\000\000\000\000\001\139\000\000\000\000\000~\000\000\000\000\002\154\000\000\000\000\000\000\000{\000\000\000\000\002\148\000\000\001\217\001\216\001\131\002v\000\000\001\154\000\000\000\000\000\000\001\151\000\000\001\156\000\000\000\000\001\152\000\000\000\000\001\153\000\000\000\000\000\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\001\169\000\000\001\145\000}\000\000\000\000\002\152\000\000\000\000\000\000\001\031\000y\001\030\000\000\000\000\002\144\000\000\001\215\001\214\001\129\002u\000\000\000\127\000\000\000\000\002\156\000\000\000\000\000\000\000\000\001\219\001\218\001\133\002w\000\000\001\161\000\000\001\165\000\000\000\000\001\157\000\000\000\000\000\000\001\150\000\000\001\155\000\000\000\000\000\000\000\000\000\000\000\000\001\164\001\138\000\000\001\163\000\000\000\000\000\000\000\000\001\160\000\000\000\000\001\159\000\000\001\158\000\000\000\000\000\000\000\000\001\162\000\000\001\166\000\000\000\000\001K\000\004\000\000\001\141\000\005\000\000\000\000\000\230\000\006\000\000\001\180\001\181\001\179\000\000\000\000\000\000\000\000\000\000\000\000\000x\000\000\000\000\002\142\000\000\000\221\001\178\001{\002\196\001}\000\000\000\007\000\000\001\183\001\184\001\182\000\000\000\000\000\000\000\000\000\000\000\000\000\231\000\234\000\000\000\000\000\000\000\000\000\239\000\241\000\240\000\235\000\237\000\236\001\187\000\000\000\000\000\000\000\000\002\201\002\212\000\000\002\202\000\000\002\203\001\127\000\000\001\177\001\185\000\000\000\000\000\000\000\000\001\223\000\000\000\000\000l\000m\000\000\000\000\000\000\001\222\000\000\000\158\000\000\001U\000\000\000\000\000\157\000\154\000\000\000\000\000\000\000\000\001\005\000\000\000\000\002\213\000\000\002\214\000\000\000\000\001\210\001\208\000\000\001\209\000\008\000\000\000\t\000\000\002\011\002\012\002\n\000\000\000\000\002\t\000\000\000\n\000\000\002\014\002\015\002\013\000\000\000\000\000\000\000\000\002\003\000\000\000\000\002\005\000\000\001\255\000\000\002\001\000\000\002\006\000\000\002\007\002\000\001\254\002\017\001\137\000\000\002\008\000\000\002\019\000\000\002\018\000\000\002\020\000\000\002y\000\011\000\000\000\000\000\229\000\012\000\000\000\000\000\000\000\000\000\000\002\021\000\000\000\000\002\024\000\000\002\023\000\000\002\022\000\198\000\000\000\000\000\000\000\000\000\199\002\025\000\000\000\000\002\131\000\000\000\000\000\000\000\000\000\000\002\134\000k\000\000\000\000\000\204\000\000\000\000\000\224\000\223\000\222\000\000\0018\000\000\002\130\001y\001w\000\000\000\000\000\000\000\000\000\000\000\000\002\129\000\000\000\013\000\000\000\000\000\000\000\000\000\000\002\132")
+ (16, "\000\000\000\000\001 \001!\000\000\001#\001\"\000\001\000\000\001[\000\000\000\000\000\136\000\000\000\000\001\214\000\142\000\145\002\197\002\196\000\146\001\013\001\019\001\015\001\018\001\017\000\135\001\011\001\026\000\000\000\000\001\025\000\000\000\000\000\000\000\000\000\000\001O\000\232\002\187\002q\000\000\000\000\000\000\000\000\000\000\002\192\000\000\001\022\000\000\002\194\000\000\001\029\001\028\000\000\000\000\002\252\002;\000\000\002\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\253\000\000\002U\000\000\000\000\002\249\002\251\002A\001\004\002@\001\002\001\003\002?\002>\002=\0029\000\000\000\000\002:\000\205\000\000\002<\000\000\002\248\000\000\002\223\001\001\002\028\000\000\000\000\002\031\000\000\000\015\000\000\000\000\000\000\000\000\000\206\0028\002D\000[\000\021\000]\000\000\000\000\000c\000\000\000\000\000\000\000\000\000\000\000\000\000\022\000\000\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\001\251\000R\000\215\000^\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\000T\000\000\000S\000\000\000\000\000\140\000\216\000\000\002\"\000\217\000\014\000\000\001\014\001\020\001\016\001\012\000\016\000\000\000\000\000\143\000\000\000\141\000\000\000\000\000\220\000\000\000\000\002\029\002 \000\000\002\030\002!\002\224\002\222\000\000\002B\002\221\000\000\002]\000\000\000\000\001\190\000\000\001i\001\171\000\000\000\000\002\\\000\000\002\240\002[\002Z\002Y\002X\002W\002S\000\000\000\000\002T\000\000\002V\000\000\000\000\002\237\002*\000\000\000\000\002-\000\000\000\000\0020\000\000\000\000\002+\002.\000\000\002,\002/\002^\002R\002\238\002\236\002\235\002\239\000\000\000\000\000\000\000g\000h\000\000\000\000\000W\000\000\000V\000\227\000\000\001\206\000\000\000\000\000\000\000\000\000\000\000\210\001\212\000\000\000\000\001s\000U\0001\000\203\000_\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\000\000\0003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002C\000\000\000\144\000\000\000\000\001\189\000\000\001g\001\170\000\000\000\000\000d\000\000\002\255\000\000\000\000\001\207\000\000\000\000\002\226\002\225\000\000\000Q\000\147\000\000\001Q\000\000\002\190\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\226\000\151\000\000\000\000\000n\000o\001\225\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\160\001\195\000\000\000\148\000\155\000\000\001\197\000\000\000\000\000\000\000\000\000\149\000\161\000\000\001W\000\000\000\000\002\189\000\000\000\000\000\138\000\000\000\000\002\188\000\000\000\000\000\000\002\191\002\195\000\000\000\000\000\000\001\023\000\000\000\214\000\000\001\024\000\000\000\000\001:\000\000\0019\000\000\001G\000\000\001]\000\000\000\000\000\000\000\000\000\000\000\000\001\008\000\000\000\000\002\219\000\000\000\189\002\218\002\183\002\185\002\186\002\184\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002b\000\000\000\000\000\000\000\000\002i\000\000\000\000\002h\002g\002f\002e\002d\0016\002`\000\000\000\000\002a\000\000\002c\000\000\000\000\002\244\0021\000\000\000\000\0024\000\000\000\000\0027\000\000\000\000\0022\0025\000\000\0023\0026\002k\002_\002\245\002\243\002\242\000i\000j\000\000\000\000\000Z\000\000\000Y\000\000\002j\000\000\001\172\000X\000?\000\226\000`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\247\002\246\000\000\002\174\000\000\002\173\000\000\000\000\000\000\000\000\003\004\000\000\000\000\000\000\003\005\000\000\000\018\000\000\000\000\000\000\003\000\000\000\001u\000\000\000\000\000\000\000\162\002\164\001M\000\000\000\153\001L\001%\001$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\207\000\208\000\195\000\000\001Y\000\000\000\000\000\194\000\190\000\000\000\197\000\191\000\196\000\000\002\176\000\000\002\175\002\161\000\000\000\000\000\000\000\000\000\000\002\170\000\000\000\000\000\000\000\000\000\000\002\171\002\163\000\000\002\177\000\000\002\165\000\000\000\166\000\000\002\180\000\152\000\000\001'\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000\000\000w\000\000\000\000\000\000\002H\000\000\000\000\000\000\002P\000\000\000\000\002O\000\000\002\233\002N\002M\002L\002K\002J\002F\000\000\000\000\002G\000\000\002I\000\000\000\000\002\230\002#\000\000\000\000\002&\000\000\000\000\002)\000\000\000\000\002$\002'\000\000\002%\002(\002Q\002E\002\231\002\229\002\228\002\232\000\000\000\000\000\000\000e\000f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\212\001(\000\000\000\000\000\000\001.\000\000\000\000\001/\000#\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\000%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001-\0012\000\000\001,\000\000\000\000\0014\000\000\000\000\000\000\000\000\000\000\000\000\000t\000q\000r\0015\0011\000\000\000\000\0010\001*\000\000\001)\000\000\000\182\000\000\002\142\000\000\000\000\000\178\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\185\000\000\000\000\000\188\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\007\000\000\000\000\000\000\000\175\000\000\000\172\000\000\000\000\000\000\000\000\000\000\000\183\000\000\000\179\000\000\000\000\002\201\000\000\002\208\000\168\000\000\000\000\000\000\000\000\000\180\000\000\000\176\000\173\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\184\000\000\000\000\000\187\000\000\002\202\000\167\000\000\002\203\000\000\002\210\000\000\000\000\000\000\000\000\000\186\000\000\000\170\000\000\000\000\000\000\000\000\001\006\000\000\000\000\000\000\000\174\000\000\000\171\000\000\000\000\000\000\000\000\000\000\000\181\000\000\000\177\000\164\000\163\000\000\002\211\002\212\000\000\002\213\000\000\002\214\000\000\001&\002\168\000\000\000\000\001\194\000\000\001q\001\176\000\000\002\162\000\000\000\000\000\000\002\167\000\000\000\000\000\000\000\250\000\000\000\244\000\000\000\245\000\000\000\255\000\243\000\254\000\000\002\179\001\000\000\000\000\169\000\000\000\000\000\000\000\000\000\252\000\247\001\191\000\000\000\248\000\000\000\249\000\000\001k\001\173\000\000\000\000\000\000\001\202\000\000\001\200\000\000\000\000\001\204\001\198\000\000\001\205\001\199\000\000\002\181\001\208\000\000\000\165\000\000\000\000\001\192\000\000\001m\001\174\000\000\003\001\000\000\002\253\000\000\002\254\000\019\000\020\000\000\000\000\002\127\000\000\002~\000\000\000\000\002\129\000\000\002\128\000\000\000\000\000\000\001\235\000\000\000\000\001\239\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\242\000\000\000\000\001\245\000\000\000\000\001\229\000\000\000\000\001\232\000\000\000\000\000\000\001\236\000\000\000\000\001\240\000\000\000\000\001\193\000\000\000\000\001\233\000\000\000\000\001\237\002|\001\230\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\241\000\000\000\000\001\244\000\000\002}\000\000\000\000\000\000\000\000\001\243\000\000\001\227\000\000\001\228\000\000\000\000\001\231\000\000\000\000\000\000\001\234\000\000\000\000\001\238\000\000\001o\001\175\000\000\002\130\000\000\000\000\000\000\003\002\000\017\000u\000\000\003\003\000\000\000\000\002\138\000\000\000\000\002\182\000a\000\000\000\000\000\000\000b\000\000\002\172\000\000\001S\002\169\000\000\000\000\001@\000\000\001?\000\000\001H\000\000\001c\000\000\000\000\000\000\001>\000\000\001=\000\000\001E\000\000\001a\000\000\000\000\000\000\001B\000\000\001A\000\000\001F\000\000\001e\000\000\000\000\000\000\001C\000\000\000\000\000\000\000\000\001<\000\000\001;\000\000\001I\000\000\001_\000\000\000\000\000\000\001D\000\002\000\000\000N\000O\000M\001J\000\003\000\000\000\000\002n\000\000\001\249\000\000\002t\002v\000\000\000\000\001\140\002u\000\128\000\000\000\000\002\160\000\000\000\000\000\000\000z\000\000\000\000\002\148\000\000\001\222\001\221\001\135\002z\002r\002s\000\000\001\167\000\000\002o\000\000\000\000\000|\000\000\000\000\002\152\000\000\001\149\000\000\000\000\001\146\000\000\000\000\000\000\001\148\000\000\001\147\000\000\000\000\000\000\000\000\000\000\000\000\001\168\000\000\001\144\000\000\001\143\000\000\000v\000\000\000\000\002\140\000\000\000\000\001\139\000\000\000\000\000~\000\000\000\000\002\156\000\000\000\000\000\000\000{\000\000\000\000\002\150\000\000\001\218\001\217\001\131\002x\000\000\001\154\000\000\000\000\000\000\001\151\000\000\001\156\000\000\000\000\001\152\000\000\000\000\001\153\000\000\000\000\000\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\001\169\000\000\001\145\000}\000\000\000\000\002\154\000\000\000\000\000\000\001\031\000y\001\030\000\000\000\000\002\146\000\000\001\216\001\215\001\129\002w\000\000\000\127\000\000\000\000\002\158\000\000\000\000\000\000\000\000\001\220\001\219\001\133\002y\000\000\001\161\000\000\001\165\000\000\000\000\001\157\000\000\000\000\000\000\001\150\000\000\001\155\000\000\000\000\000\000\000\000\000\000\000\000\001\164\001\138\000\000\001\163\000\000\000\000\000\000\000\000\001\160\000\000\000\000\001\159\000\000\001\158\000\000\000\000\000\000\000\000\001\162\000\000\001\166\000\000\000\000\001K\000\004\000\000\001\141\000\005\000\000\000\000\000\230\000\006\000\000\001\180\001\181\001\179\000\000\000\000\000\000\000\000\000\000\000\000\000x\000\000\000\000\002\144\000\000\000\221\001\178\001{\002\198\001}\000\000\000\007\000\000\001\183\001\184\001\182\000\000\000\000\000\000\000\000\000\000\000\000\000\231\000\234\000\000\000\000\000\000\000\000\000\239\000\241\000\240\000\235\000\237\000\236\000\000\000\000\002\199\001\188\001\187\000\000\000\000\000\000\000\000\002\204\002\215\000\000\002\205\000\000\002\206\001\127\000\000\001\177\001\185\000\000\000\000\000\000\000\000\001\224\000\000\000\000\000l\000m\000\000\000\000\000\000\001\223\000\000\000\158\000\000\001U\000\000\000\000\000\157\000\154\000\000\000\000\000\000\000\000\001\005\000\000\000\000\002\216\000\000\002\217\000\000\000\000\001\211\001\209\000\000\001\210\000\008\000\000\000\t\000\000\002\012\002\013\002\011\000\000\000\000\002\n\000\000\000\n\000\000\002\015\002\016\002\014\000\000\002\018\000\000\000\000\000\000\002\004\000\000\000\000\002\006\000\000\002\000\000\000\002\002\000\000\002\007\000\000\002\008\002\001\001\255\002\019\001\137\000\000\002\t\000\000\002\021\000\000\002\020\000\000\002\022\000\000\002{\000\011\000\000\000\000\000\000\000\000\000\000\000\000\002\023\000\000\000\000\002\026\000\000\002\025\000\000\002\024\000\198\000\000\000\000\000\000\000\000\000\199\002\027\000\000\000\000\002\133\000\000\000\229\000\012\000\000\000\000\000\000\000\000\000\000\000\000\002\136\000k\000\000\000\000\000\204\000\000\000\000\000\224\000\223\000\222\000\000\0018\000\000\002\132\001y\001w\000\000\000\000\000\000\000\000\000\000\000\000\002\131\000\000\000\013\000\000\000\000\000\000\000\000\000\000\002\134")
let error =
- (163, "\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\000\000\004\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\252\000\000\000\000\000\000\000=j\184\001\000@\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000@0\128\000 \152\019\000\128 \001\000\000\019!\136\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\002\000\128\000\004\000 \000\000\000\000\000\000\000\000\000\000\000%Q\128 \024@\000XL\t\128@\016\017\000\128\000\t\144\197\235U\192\008\002\000\000\016\128\128\000\000\000\002\000\001\000\000\000\000\000\000\000\000\000\000\000\001\001\000\000\000\000\000\000\000\000\000\000\000\000\018(\192\000\000 \000 $\004\192 \000\008\128@\000\004\192b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015Z\174\002@\016\000\000\132\004\000\000\000\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000=j\184\001\000@\000\002\016\016\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\000\008\000\000\000\000\000\000\245\170\224\004\001\000\000\008@@\000\000\000\001\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015Z\174\000@\016\000\000\132\004\000\000\000\000\016\000\008\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000 \000\000\000\000\000\000\000@\000\017\000\000\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\008\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130z\213p\002\164\128\t\007\002\160\221\160\000$\128\128@\004 \016OZ\174\000T\144\001 \224T\027\180\000\004\144\016\008\000\132\002\008\000\000\000B\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002A\192\1607h\000\t \000\001\008\004\016\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\004\131\129@n\208\000\018@@ \002\016\008 \000\000\000\n@\000\144p(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001 \224P\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\004\131\129@n\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\0180M\156\150\000\000P\004 \000;\160\"xw\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\n\146\000$\028\n\131~\128\000\146\002\001\000\016\144A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000 \131\001,\000\000\160\000\000\000v@\004\208\238\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\144\000\144\130lD\176\000\002\128 \000\001\217\000\019\195\184\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\144\130lD\176\000\002\128 \000\001\153\000\019\193\184\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\000HA6\"X\000\001@\016\000\000\204\128\t\224\220\000\000\000\002\144\000$\028\n\003v\128\000\146\002\001\000\016\128A\000\000\001 \001!\004\216\137`\000\005\000@\000\0032\000'\131p\000\000\000\n@\000\144p(\013\218\000\002H\008\004\000B\001\004\000\000\004\128\004\132\019b%\128\000\020\001\000\000\012\200\000\158\013\192\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\001\000\016\128A\000\000\001 \001!\004\216\137`\000\005\000@\000\0032\000'\131p\000\000\000\n@\000\144p(\013\218\000\002H\008\004\000B\001\004\000\000\004\128\004\132\019b%\128\000\020\001\000\000\012\200\000\158\013\192\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\018\000\018\016M\136\150\000\000P\004\000\0003 \002x7\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000H\000HA6\"X\000\001@\016\000\000\204\128\t\224\220\000\000\000\002\144\000$\028\n\003v\128\000\146\002\001\000\016\128A\000\000\001 \001!\004\216\137`\000\005\000@\000\0032\000'\131p\000\000\000\n@\000\144p(\013\218\000\002H\008\006\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\004\000B\001\004\000\000\004\128\004\132\019b%\128\000\020\001\000\000\012\200\000\158\013\192\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\018\000\018\016M\136\150\000\000P\004\000\0003 \002x7\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000H\000HA6\"X\000\001@\016\000\000\204\128\t\224\220\000\000\000\002\144\000$\028\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\008\006\000\000\004\019\000\000\000\004\004\000 \000\002d\001\001*\140\001\000\194\000\002\130`L\002\000\128\136\004\000\000L\134 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\244\224\008\006\016\000\020\019\002`\016\004\004@ \000\002d1\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000u\170\160\004\001\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\001\000\194\000\000\130`L\002\000\128\128\004\000\000L\134 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\000=j\184\001R@\004\131\129Po\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\004\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015Z\174\000T\144\001 \224T\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000H8\020\006\237\000\001$\004\000\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001 \224P\027\180\000\004\144\016\000\000\132\002\008\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128\004\136\017e%\000\000\016\001\008\000\006\168\008\134\017\192\000\000\000\000\000\000\000\000\000\002\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\002\164\128\t\007\002\160\223\160\000$\128\128@\004$\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\004\131\129@n\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\002\164\128\t\007\002\160\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128\004\128\017`%\000\000\016\001\000\000\006\136\000\134\017\192\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\128\000\004\000\000\000\000\004)\000\002A\192\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\128\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \001 \004X\t@\000\004\000@\000\001\"\000!\128p\000\000\000\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\004\128\004\128\017`%\000\000\016\001\000\000\004\136\000\134\001\192\000\000\000)\000\002A\192\1607h\000\t \000\001\008\004\016\000\000\018\000\018\000E\128\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128\000\004 \016@\000\000H\000H\001\022\002P\000\001\000\016\000\000H\128\008`\028\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002A\192\1607h\000\t \000\001\008\004\016\000\000\018\000\018\000E\128\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128\000\004 \016@\000\000H\000H\001\022\002P\000\001\000\016\000\000H\128\008`\028\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\001 \001 \004X\t@\000\004\000@\000\001\"\000!\128p\000\000\000\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\004\128\004\128\017`%\000\000\016\001\000\000\004\136\000\134\001\192\000\000\000)\000\002A\192\1607h\000\t \000\001\008\004\016\000\000\018\000\018\000E\128\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128`\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\000\000B\001\004\000\000\004\128\004\128\017`%\000\000\016\001\000\000\004\136\000\134\001\192\000\000\000)\000\002A\192\1607h\000\t \000\001\008\004\016\000\000\018\000\018\000E\128\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128\000\004 \016@\000\000H\000H\001\022\002P\000\001\000\016\000\000H\128\008`\028\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\002\000\003\214\171\128\016\004\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001 \224P\027\180\000\004\144\016\000\000\132\002\008\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000*H\000\144p*\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000@\000\000\000\000\000\000\000\128\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\020`\000\000\016\000\016\018\002`\016\000\004@ \000\002`1\001\"\140\000\000\002\000\002\000@L\002\000\000\136\004\000\000L\006 \000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000\128 \000\001\000\008\192\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\016\016\000\000\000\000\000\000\000\000\002 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\000=j\184\001\000@\000\002\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\128\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000=j\184\001\000@\000\002\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004@\000\245\170\224\004\001\000\000\008\000F\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000D\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\016\004\000\000 \001\024\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\002\000\128\000\004 \000\000\000\000\128\000\000\000\000\128\015Z\174\000@\016\000\000\132\004\000\000\000\000\016\000\008\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\181T\000\128 \000\000\000\008\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\149F\000\128a\000\001a0&\001\000@D\002\000\000&C\023\173W\000 \008\000\000B\002\000\000\000\000\008\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000@\000\000\000\000\000\000\023\173W\000 \008\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000\128 \000\001\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\255_\130.I\000\128f+\143\222\016\007\234\024\000\141b\005\004\002E\024\000\000\000\000\004\004\000\152\000\000\001\016\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\016\004\000\000 \001\024\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000=j\184\001\000@\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000 \228\016\008\006B\136\253\161\000~\161\128\008\198 P@\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\003\255\175\193\023$\128H:\021\199\239\008\003\245\012\002G\177\134\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001\000\192P\027\180\000\012\144\016\000\000\132\002\008\000\000\000\002\144\000 \024\n\003v\128\001\146\002\000\000\016\128A=j\184\001R@\004\131\129Pn\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\005 \000@0\020\006\237\000\003$\004\000\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000@0\020\006\237\000\003$\004\000\000!\000\130\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000 \024\n\003v\128\001\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\128`(\013\218\000\006H\008\000\000B\001\004\000\000\000\001H\000\016\012\005\001\187@\000\201\001\000\000\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002@\002F\t\179\146\192\000\n\000\132\000\007T\004\n\014\224\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000=j\184\001R@\004\131\129Po\208\000\018@@ \002\018\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002A\192\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000$ \155\017,\000\000\160\008\000\000t@\000\160\238\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\000HA6\"X\000\001@\016\000\000\200\128\001@\220\000\000\000\002\144\000 \024\n\003v\128\001\146\002\000\000\016\128A\000\000\001 \001!\004\216\137`\000\005\000@\000\003\"\000\005\003p\000\000\000\n@\000\128`(\013\218\000\006H\008\000\000B\001\004\000\000\004\128\004\132\019b%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000)\000\002\001\128\1607h\000\025 \000\001\008\004\016\000\000\018\000\018\016M\136\150\000\000P\004\000\0002 \000P7\000\000\000\000\164\000\008\006\002\128\221\160\000d\128\128\000\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000 \024\n\003v\128\001\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\128`(\013\218\000\006H\008\000\000B\001\004\000\000\004\128\004\132\019b%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000)\000\002\001\128\1607h\000\025 \000\001\008\004\016\000\000\018\000\018\016M\136\150\000\000P\004\000\0002 \000P7\000\000\000\000\164\000\008\006\002\128\221\160\000d\128\128\000\004 \016@\000\000H\000HA6\"X\000\001@\016\000\000\200\128\001@\220\000\000\000\002\144\000 \024\n\003v\128\001\146\002\000\000\016\128A\000\000\001 \001!\004\216\137`\000\005\000@\000\003\"\000\005\003p\000\000\000\n@\000\128`(\013\218\000\006H\008\000\000B\001\004\000\000\004\128\004\132\019b%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000)\000\002A\192\1607h\000\t \024\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\164\000\008\006\002\128\221\160\000d\128\128\000\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000 \024\n\003v\128\001\146\002\000\000\016\128A\000\000\001 \001!\004\216\137`\000\005\000@\000\003\"\000\005\003p\000\000\000\n@\000\128`(\013\218\000\006H\008\000\000B\001\004\000\000\004\128\004\132\019b%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000)\000\002\001\128\1607h\000\025 \000\001\008\004\016\000\000\018\000\018\016M\136\150\000\000P\004\000\0002 \000P7z\213p\002\164\128\t\007\002\160\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@ \144p(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\2482\228\144\008\006b\184\253\225\000~\161\128\008\214 P@\000\000\000\002\000\000\000\002\000\000\000\000\000\000B \000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\017rH\004\003!\\~\240\128?P\192\004k\016('\255_\130.I\000\144t/\143\222\016\007\234\024\004\141b\133\004\255\235\240e\201 \016\012\197q\251\194\000\253C\000\017\172@\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\191\225\151$\128@3\023\199\239\024\003\245L G\177\198\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\191\004\\\146\001\000\204W\031\188 \015\2120\001\026\196\n\t\255\215\224\139\146@$\029\011\227\247\132\001\250\134\001#X\161A?\250\252\017rH\004\131\161\\~\240\128?P\192$k\016h \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\0180M\156\150\000\000P\004 \000;\160\"Pw\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\007 \128@2\020G\237\008\003\245\012\000F1\002\130\000\000\000 \228\016\008\006B\136\253\161\000~\161\128\008\198 P@\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\004\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \016H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001 \224P\027\180\000\004\144\016\008\000\132\130\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\016r\008\004\003!D~\208\128?P\192\004c\016( \000\000\002\014A\000\128d(\143\218\016\007\234\024\000\140b\005\004\000\000\000\000\000\000\000\000\000\000\016\000\000\001\000\000\128\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\136\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000 \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002@\002\006\0082\146\192\000\008\000\004\000\0034\004H\008\192\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\n\146\000$\028\n\131~\128\000\146\002\001\000\016\144A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\002\014A\000\128d(\143\218\016\007\234\024\000\140b\005\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\017rH\004\131\161\\~\240\128?P\192$k\016( \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\239\248e\201 \016\012\197\241\251\198\000\253S\008\017\236q\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\008\002\000\000\016\000\128\000\000\000\002\000\000\000\000\000\000\000\145F\000\000\000\000\001\001\000&\000\000\000D\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\245\170\224\004\001\000\000\008\000F\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\128\000 \000\000\000\000\000\n@\000\144t(\013\218\000\002H\008\004\000B\001\004\000\000\000\001H\000\016\013\133\001\187@\000\201\001\000\160\008A \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000@0\020\006\237\000\003$\004\000\000!\000\130\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000=j\184\001R@\004\131\129Pn\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002\001\128\1607h\000\025 \000\001\008\004\016\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001\000\192P\027\180\000\012\144\016\000\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\004\003\001@n\208\0002@@\000\002\016\008 \000\000\000\n@\000\128`(\013\218\000\006H\008\000\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\016 A\148\148\000\000@\000 \000\016\160\"\000\006\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\n\146\000$\028\n\131~\128\000\146\002\001\000\016\144A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\n\146\000$\028\n\131v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\n@\000\128`(\013\218\000\006H\008\000\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000H8\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\001\000\000\000\000\000\020\128\001 \224P\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\n@\000\128l(\013\218\000\006H\008\001\000B\001\004\000\000\000\001H\000\016\013\133\001\187@\000\201\001\000\160\008A \128\000\000\004)\000\002\001\176\1607h\000\025 \020\001\008$\016\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\t\007B\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000)\000\002\001\176\1607h\000\025 \004\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\020\128\001\000\216P\027\180\000\012\144\016\002\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000 \000\131\001(\000\000\128\000\000\000 @\004\000\012\000\000\000\001H\000\016\012\005\001\187@\000\201\001\000\000\008@ \128\000\000\128\000\128\002\012\004\160\000\002\000\000\000\000\129\000\016\0000\000\000\000\005 \000@0\020\006\237\000\003$\004\000\000!\000\130\000\000\002\000\002\000\0080\018\128\000\008\000\000\000\002\004\000@\000\192\000\000\000\020\128\001\000\192P\027\180\000\012\144\016\000\000\132\002\008\000\000\008\000\008\000 \192J\000\000 \000\000\000\008\016\001\000\003\000\000\000\000R\000\004\003\001@n\208\0002@@\000\002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\016\012\005\001\187@\000\201\001\000\000\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000@0\020\006\237\000\003$\004\000\000!\000\130\000\000\002\000\002\000\0080\018\128\000\008\000\000\000\002\004\000@\000\192\000\000\000\020\128\001\000\192P\027\180\000\012\144\016\000\000\132\002\008\000\000\008\000\008\000 \192J\000\000 \000\000\000\008\016\001\000\003\000\000\000\000R\000\004\003\001@n\208\0002@@\000\002\016\008 \000\000 \000 \000\131\001(\000\000\128\000\000\000 @\004\000\012\000\000\000\001H\000\016\012\005\001\187@\000\201\001\000\000\008@ \128\000\000\128\000\128\002\012\004\160\000\002\000\000\000\000\129\000\016\0000\000\000\000\005 \000@0\020\006\237\000\003$\004\000\000!\000\130\000\000\002\000\002\000\0080\018\128\000\008\000\000\000\002\004\000@\000\192\000\000\000\020\128\001\000\192P\027\180\000\012\144\016\000\000\132\002\008\000\000\008\000\008\000 \192J\000\000 \000\000\000\008\016\001\000\003\000\000\000\000R\000\004\003\001@n\208\0002@@\000\002\016\008 \000\000 \000 \000\131\001(\000\000\128\000\000\000 @\004\000\012\000\000\000\001H\000\016\012\005\001\187@\000\201\001\000\000\008@ \128\000\000\128\000\128\002\012\004\160\000\002\000\000\000\000\129\000\016\0000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\n@\000\128l(\013\218\000\006H\008\005\000B\t\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002\001\176\1607h\000\025 \020\001\008$\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\164\000\008\006\194\128\221\160\000d\128\128P\004 \144@\000\000\000\020\128\001\000\216P\027\180\000\012\144\016\002\000\132\018\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000R\000\004\003a@n\208\0002@@(\002\016H \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\002\144\000 \027\n\003v\128\001\146\002\000@\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000=j\184\001\000@\000\002\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000H:\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0010\000\000\002\000\000\000\000\000\000\000\000\000\000\000\001\000\001@\000\000\000\000\000\000\000\128\000 \000\000\000\000\000\000\000 \000(\000\000\000\000\000\000\000\016\000\004\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000\128 \000\001\000\008\192\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\004\000\001\000\000\000\000\000\000R\000\004\131\161@n\208\000\018@@ \002\016\008 \000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000:\213P\002\000\128\000\000\000 \000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\004\000\001\000\000\000\000\000\000R\000\004\131\161@n\208\000\018@@ \002\016\008 \000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248\"\228\144\008\006b\184\253\227\000~\161\128\008\214 P@\000\000\000\000\000\000 \000\000\000@\000\000\000\136\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\017rH\004\0031\\~\241\128?P\194\004k\016+0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\145\130l\228\176\002\002\128! \001\221\001\002\131\184\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\008\000\002\000\000\000\000\000\000\164\000\t\007B\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000=j\184\001\000@\000\002\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000H:\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\004\004\000\000\000\008\000\000\000\017\000\000\000\024\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\235\240E\201 \018\014\133q\251\198\000\253C\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\175\193\023$\128@3\021\199\239\024\003\245\012 F\177\002\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\n\146\000$\028\n\131~\128\000\146\002\001\000\016\144A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\019\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\015Z\174\000@\016\000\000\128\004`\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\002\000\000\128\000\000\000\000\000)\000\002A\208\1607h\000\t \016\001\008\004\016\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\029j\168\001\000@\000\000\000\016\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\008\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\002\000\000\128\000\000\000\000\000)\000\002A\208\1607h\000\t \016\001\008\004\016\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\235\240E\201 \018\014\133q\251\198\000\253C\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\001\001\000\000\000\002\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\255\215\224\139\146@$\029\n\227\247\140\001\250\134\001#X\129A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\004\192 \000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000@\000\000\000\000 \228\016\008\006B\136\253\161\000~\161\128\008\198 P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\002\000\000\000\000\000\000\000\000\000@\000\127\247\252\"\228\208\t\135B\248\253\227\000\254\169\132\200\246:\214`\000\000\004\028\130\001\000\200Q\031\180 \015\2120\001\024\196\n\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\017rH\004\0031|~\240\128?P\192\004{\028h \000\000\000\000\000\000\016\016\000\000\000\000\000\000\000\004\000\000\000\000\255\235\240E\201 \016\012\197\241\251\194\000\253C\000\017\236q\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\008\008\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\191\004\\\146\001 \232_\031\188 \015\2120\t\030\199\026\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\017rH\004\131\161|~\240\128?P\192${\028h \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\128\000\255\235\240E\201 \016\012\197\241\251\194\000\253C\000\017\172P\160\128\000\000\000\000\000\000@@\016\000\000\000\000\000\000\016\000\002\000\003\255\175\193\023$\128@3\023\199\239\008\003\245\012\000F\177B\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\128\128 \000\000\000\000\000\000 \000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\235\240E\201 \018\014\133\241\251\194\000\253C\000\145\172P\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\001\0010\000\000\002\000\000\000\000 \000\000\000\000\000\000 \000\192\128\000\000\000\000@\000\000 \000\001\000\023\255_\130.I\000\128f+\143\222\016\007\234\024\000\141b\005\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\128`@\000\000\000\000 \000\000\016\000\000\128\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248\"\228\208\t\135B\184\253\225\000\254\161\128H\214\"Po\254\191\004\\\146\001\000\204W\031\188 \015\2120\001\026\196\n\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\255_\130.M\000\152t+\143\222\016\015\234\024\004\141b%\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\128\000\255\235\240E\201 \018\014\133\241\251\194\000\253C\000\145\172P\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \016\016\000\000\000 \000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\253~\008\185$\002A\208\174?x\192\031\168`\0185\136\020\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\239\215\224\n\146@ \024\n\131w\128\001\146\002\000\000X\129A\000\000\000\000R\001\004\131\129@n\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\223\175\192\021$\128@0\021\006\239\000\003$\004\000\000\177\002\130\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000 \008\000\000@\002\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\t\007B\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000z\213p\002\000\128\000\004\000#\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144t(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002`\000\000\004\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\029\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000u\170\160\004\001\000\000\000\000@\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001 \232P\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\128\000\247\235\240\005I \016\012\005A\187\192\000\201\001\000\000,@\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\0160A\148\150\000@@\000$\000\024\160 @F\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\029\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000 \008\000\000@\0020\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\t\007B\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000\169 \002A\192\1687\232\000\t \016\001\t\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\0010\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002A\208\1607h\000\t \016\001\008\004\016\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007Z\170\000@\016\000\000\000\004\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\002\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\018\014\133\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\128\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\128\000\000\016\019\000\000\000 \000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\128\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248\"\228\144\008\006b\184\253\225\000~\161\128\008\214 P@\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000\144p(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\031\253~\008\185$\002A\208\174?x@\031\168`\018=\1404\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128B\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\001\000\000\000\000\000\000\000_\253~\008\185$\002\001\152\174?x@\031\168`\0025\136\020\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248\"\228\144\008\006b\184\253\225\000~\161\128\008\214 P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\008\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\002A\192\1607h\000\t \000\001\008\004\016\000\000\000\000\002\000\000\000\000\000\000\000\004\000\000\000\000\000\000\001\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128\000\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000 \000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \228\016\008\006B\136\253\161\000~\161\128\008\198 P@\000\000\000\000\008\000\000\000\000\000\000\000\016\000\000\000\000\000\000\004\000\000\000\131\144@ \025\n#\246\132\001\250\134\000#\024\129A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\014A\000\128d(\143\218\016\007\234\024\000\140b\005\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\128\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000 \000\000\000\000\000\000\000@\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\253~\000\128 \000\001\000\008\000\016\000\000 \000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\128\000\000\000\000\000\000/\254\191\000@\016\000\000\128\004\000\008\000\000\016\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\001\000@\000\002\000\016\000 \000\000@\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\004\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\001 \224P\027\180\000\004\144\016\000\000\132\002\008\000\000\000\000\001\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\!\194\"$\129\016\008\000\001 \000U\t\000\002`\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000p\136\136 D\002\000\000H\000\021B@\000\152\000\000\245\170\224\014\017\000\004\008\128@\000\t\000\002\168H\000\019\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\008\004\002\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000 \016\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\008\000\000\000 \000\004\002\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\001\000\000\000\000\000\000\004\000\000\000\000\000\000\001\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\128\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000p\136\128 D\002\000\000H\000\021B@\000\136\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\001\194 \000\129\016\008\000\001 \000U\t\000\002 \000\000\000@\000\008\004\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\008\000\000\000 \000\004\002\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000@ \000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000 \016\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000 \000\004\002\000\000\000\000\000\000@\000\002\000\016\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\008\004\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\008\000\001\000\128\000\000\128\000\000\016\000\000\128\004\000\000@\000\000\001\000\000 \016\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\004\000\000\128@\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\008\002\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\008\000\245\170\224\004\001\000\000\008\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\008\000\001\000\128\000\000\130\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001@\000\000\000\000\000\000\004\000\000\128@\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\128\000\000\002\000\000@ \000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000#\000\000\004\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000@ \000\000\001\000\000\000\000\000 \001\000\000\000\000\000\000@\000\008\004\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\016\008\000\000\000\000\000\000\000\000\008\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\008\004\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\004\000\000\128@\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000@ \000\000\000\128\000\000\000\000 \001\000\000\000\000\000\000@\000\008\004\000\000\004\128\000\000\128\000\004\000 \000\002\000\000\000\008\000\001\000\128\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000 \000\004\002\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000@\000\000\001\000\000 \016\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\008\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\004\000\000\000\000\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000 \016\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000 \000\000\000\128\000\016\008\000\000\000\000\000\000\000\000\008\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\004\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\004\002\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\002\001\000\000\000\008\000\000\000\000\001\000\008\000\000\000\000\000\002\000\000@ \000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000=n\184\001\128@\000\002 \016\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\002\000\000@ \000\000\004\128\000\004\000\000 \001\000\000\016\000\000\000@\000\008\004\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\030\183\\\000\192 \000\001\016\136\000\000\000\000 \001\000\000\000\000\000\000@\000\008\004\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\004\002\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\008\004\000\000\004\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\001\000\000 \016\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\194\028\"\"H\017\000\128\000\018\000\005P\144\000&\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\018\014\007\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\001\136\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\028\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\016\000\000\000\000\001H\000\018\014\005\001\187@\000I\001\000\000\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\239\248E\201 \018\014\135q\251\194\000\253S\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\251\254\017rH\004\131\161\\~\240\128?T\194$k\016+3\191}\192 \008\000\000\000\002\000\000\000\000\000\128\000\000\000\000\000\002E\024\000\000\000\000\000\004\000\000\000\000\000\016\000\000\000\000\000\014\253\247\000\128 \000\000\000\008\000\000\000\000\002\000\000\000\000\000\001\223\190\224\016\004\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\001\"\140\000\000\000\000\000\002\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\145F\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\018(\192\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\002E\024\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000H\163\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\253\255\000\128 \000\001\000\008\000\000\000\000\"\000\000\000\000\000\000\t\020`\000\000\000\000\016\000\000\000\000\000\000@\000\000\000\000\000\127\245\248\"\228\144\008\006b\184\253\225\000~\161\128\008\214 P@\000\000\000\000\000\000 \000\000\000\000\000\000\000\136\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \016\016\000\000\000\000\000\000\000D\000\000\000b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\253~\008\185$\002A\208\174?x@\031\168a\0185\136\021\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\152\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\016\004\000\000 \001\024\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\128\001\235U\192\008\002\000\000\016\000\140\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\136\000\030\181\\\000\128 \000\001\000\008\192\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\017rH\004\131\161\\~\240\128?P\192$k\016h \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\163\000\000\000\000\000\128\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\016\008\008\000\000\000\000\000\000\000\"\000\000\0001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\191\004\\\146\001 \232W\031\188 \015\2120\137\026\196\n\204\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000&\000\000\000@\002\000\000\000\003\016\000\000\000\000\016\016\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000$\028\014\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\t\007\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\251\254\017rH\004\131\161\220~\240\128?T\194$k\016+0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\255\132\\\146\001 \232W\031\188 \015\2130\137\026\196\n\205\255\223\240\139\146@ \025\138\227\247\132\001\250\166\016#X\129Y\128\000\000\000\000\000\000\128\128\000\000\000\000\000\000\002 \000\000\003\023\255\127\194.I\000\128f+\143\222\016\007\234\152@\141b\005f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\253\255\008\185$\002A\208\174?x@\031\170a\0185\136\021\155\255\191\225\023$\128@3\021\199\239\008\003\245L F\177\002\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@ \000\000\000\000\000\000\000\136\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\251\254\017rH\004\131\161\\~\240\128?T\194$k\016+0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\239\248E\201 \018\014\133q\251\194\000\253S\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\191\225\023$\128H:\021\199\239\008\003\245L\"F\177\002\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\012@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\191\225\023$\128H:\021\199\239\008\003\245L\"F\177\002\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@ \000\000\000\000\000\000\000\136\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\251\254\017rH\004\131\161\\~\240\128?T\194$k\016+0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\152\000\000\001\000\008\000\000\000\012@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000 \000\000\000\000\000\000\000\000\130p\003\000\000\002\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\002\000\000\000\000\000\000\000\000\000'\0020\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\128\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\002\008\000\000\000\000\000\000\008\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\008 \000\000\000\000\000\000 \000\000\000@\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\016\002\000\000\000\000\000@\000\001\004\000\000\000\000\000\000\004\000\000\000\008\000\000\000\000\128\002\000\002\000\000\000\000\000\000\000#\000 \000@(\000\000\000\000\001\000\000\004\016\000\000\000\000\000\000\016\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000 \000 \000\000\000\000\000\000\0020\002\000\000\002\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\016\000\000\000\000\000\000\000\000\001\024\001\128\000\001\000\000\000\000\128\002\000\000\000\000\000\000\000\000\000#\000 \000\000 \000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\140\000\128\016\000\128\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\008\192\008\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\004`\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000 \000\000\000\000\000\000\000\000\0020\003\000\000\002\000\000\000\001\000\004\000\000\000\000\000\000\000\000\000F\000@\000\000@\000\000\000\000\000\128\000\000\000\000\000\000\000\000\008\192\008\000\000\008\000\000\000\000\000\016\000\000\000\000\000\000\000\000\001\024\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")
+ (167, "\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\000\000\000\000\016\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\192\000\000\000\000\000\000\003\214\171\128\004\000\128\000\004\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\016\006\016\000\002\t\1290\008\002\002\000\016\000\0012\024\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\000\128\016\000\000\128\002\000\000\000\000\000\000\000\000\000\000\000\002U\024\000\1280\128\000\152L\t\128@\016\017\000\128\000\t\144\197\235U\192\002\000@\000\002\008\008\000\000\000\000 \000\016\000\000\000\000\000\000\000\000\000\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\018(\192\000\000\004\000\004\002@L\002\000\000\136\004\000\000L\006 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\245\170\224\t\000 \000\001\004\004\000\000\000\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\004\000\128\000\004\016\016\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\008\000\000\000\128\000\000\000\000\000\015Z\174\000\016\002\000\000\016@@\000\000\000\001\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\245\170\224\001\000 \000\001\004\004\000\000\000\000\016\000\008\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\002\000\000\000\000\000\000\000\004\000\001\016\000\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\008\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130z\213p\000\169\016\001 \208*\013\218\000\002H\008\004\000B\001\004\245\170\224\001R \002A\160T\027\180\000\004\144\016\008\000\132\002\008\000\000\000\016\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\t\006\129@n\208\000\018@@ \002\016\008 \000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002A\160P\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\t\006\129@n\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \000D`\155,\150\000\000P\004 \000;\160\"xw\000\000\000\000\000\000\000\000\000\000\000\128\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\002\164@\004\131@\1687\232\000\t \016\001\t\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\008\004\016`\018\192\000\n\000\000\000\007d\000M\014\224\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\144\000\"\016M\132K\000\000(\002\000\000\029\144\001<;\128\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\"\016M\132K\000\000(\002\000\000\025\144\001<\027\128\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128\001\016\130l\"X\000\001@\016\000\000\204\128\t\224\220\000\000\000\000\164\000\004\131@\1607h\000\t \016\001\008\004\016\000\000\018\000\004B\t\176\137`\000\005\000@\000\0032\000'\131p\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000H\000\017\008&\194%\128\000\020\001\000\000\012\200\000\158\013\192\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\001 \208(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \016\001\008\004\016\000\000\018\000\004B\t\176\137`\000\005\000@\000\0032\000'\131p\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000H\000\017\008&\194%\128\000\020\001\000\000\012\200\000\158\013\192\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\001 \000D \155\008\150\000\000P\004\000\0003 \002x7\000\000\000\000)\000\001 \208(\013\218\000\002H\008\004\000B\001\004\000\000\004\128\001\016\130l\"X\000\001@\016\000\000\204\128\t\224\220\000\000\000\000\164\000\004\131@\1607h\000\t \016\001\008\004\016\000\000\018\000\004B\t\176\137`\000\005\000@\000\0032\000'\131p\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128`\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000H\000\017\008&\194%\128\000\020\001\000\000\012\200\000\158\013\192\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\001 \000D \155\008\150\000\000P\004\000\0003 \002x7\000\000\000\000)\000\001 \208(\013\218\000\002H\008\004\000B\001\004\000\000\004\128\001\016\130l\"X\000\001@\016\000\000\204\128\t\224\220\000\000\000\000\164\000\004\131@\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000 \012\000\000\004\019\000\000\000\004\004\000 \000\002d\001\001*\140\000@\024@\000H&\004\192 \008\008\128@\000\004\200b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\191N\000 \012 \000$\019\002`\016\004\004@ \000\002d1\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007Z\170\000\016\002\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000@\024@\000\008&\004\192 \008\008\000@\000\004\200b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\000\003\214\171\128\005H\128\t\006\129Po\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\004\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\245\170\224\001R \002A\160T\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\000\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002A\160P\027\180\000\004\144\016\000\000\132\002\008\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\000\017\016\"\201%\000\000\016\001\008\000\006\168\008\134\017\192\000\000\000\000\000\000\000\000\000\000 \000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\000\169\016\001 \208*\013\250\000\002H\008\004\000BA\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\t\006\129@n\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\000\169\016\001 \208*\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\000\017\000\"\192%\000\000\016\001\000\000\006\136\000\134\017\192\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\001 \208(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\128\000\004\000\000\000\000\001\n@\000H4\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\001 \208(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\128\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\004@\008\176\t@\000\004\000@\000\001\"\000!\128p\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000H\000\017\000\"\192%\000\000\016\001\000\000\004\136\000\134\001\192\000\000\000\n@\000H4\n\003v\128\000\146\002\000\000\016\128A\000\000\001 \000D\000\139\000\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000)\000\001 \208(\013\218\000\002H\008\000\000B\001\004\000\000\004\128\001\016\002,\002P\000\001\000\016\000\000H\128\008`\028\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\000\000\016\128A\000\000\001 \000D\000\139\000\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000)\000\001 \208(\013\218\000\002H\008\000\000B\001\004\000\000\004\128\001\016\002,\002P\000\001\000\016\000\000H\128\008`\028\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\018\000\004@\008\176\t@\000\004\000@\000\001\"\000!\128p\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000H\000\017\000\"\192%\000\000\016\001\000\000\004\136\000\134\001\192\000\000\000\n@\000H4\n\003v\128\000\146\002\000\000\016\128A\000\000\001 \000D\000\139\000\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000)\000\001 \208(\013\218\000\002H\008\006\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128\000\004 \016@\000\000H\000\017\000\"\192%\000\000\016\001\000\000\004\136\000\134\001\192\000\000\000\n@\000H4\n\003v\128\000\146\002\000\000\016\128A\000\000\001 \000D\000\139\000\148\000\000@\004\000\000\018 \002\024\007\000\000\000\000)\000\001 \208(\013\218\000\002H\008\000\000B\001\004\000\000\004\128\001\016\002,\002P\000\001\000\016\000\000H\128\008`\028\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000 \000=j\184\000@\008\000\000@\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002A\160P\027\180\000\004\144\016\000\000\132\002\008\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000\n\145\000\018\013\002\160\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000@\000\000\000\000\000\000\000\128\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\145F\000\000\000 \000 \018\002`\016\000\004@ \000\002`1\001\"\140\000\000\000@\000@\004\004\192 \000\008\128@\000\004\192b\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000 \004\000\000 \000\140\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000 \016\000\000\000\000\000\000\000\000\002 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\000\003\214\171\128\004\000\128\000\004\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\128\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\004\000\128\000\004\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000D\000\015Z\174\000\016\002\000\000\016\000F\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\008\000\000\000\004@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000=j\184\000@\008\000\000@\001\024\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\213p\000\128\016\000\000\130\002\000\000\000\000\008\000\000\000\000\008\000\245\170\224\001\000 \000\001\004\004\000\000\000\000\016\000\008\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\181T\000 \004\000\000\000\000\128\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\tT`\002\000\194\000\002a0&\001\000@D\002\000\000&C\023\173W\000\008\001\000\000\008 \000\000\000\000\128\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000@\000\000\000\000\000\000\023\173W\000\008\001\000\000\008\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000 \004\000\000 \000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000 \000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\255_\130\011\145 \016\012b\184\253\225\000~\161\128\008\214 P@$Q\128\000\000\000\000\008\004\000\152\000\000\001\016\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000=j\184\000@\008\000\000@\001\024\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\004\000\128\000\004\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000 9\002\001\000\196(\143\218\016\007\234\024\000\140b\005\004\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000?\250\252\016\\\137\000\144j\021\199\239\008\003\245\012\002G\177\134\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002\001\128P\027\180\000\012\144\016\000\000\132\002\008\000\000\000\000\164\000\004\003\000\1607h\000\025 \000\001\008\004\019\214\171\128\005H\128\t\006\129Pn\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\020\128\000\128`\020\006\237\000\003$\004\000\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\128`\020\006\237\000\003$\004\000\000!\000\130\000\000\000\000)\000\001 \208(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\003\000\1607h\000\025 \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\016\012\002\128\221\160\000d\128\128\000\004 \016@\000\000\000\005 \000 \024\005\001\187@\000\201\001\000\000\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002@\000\136\1936Y,\000\000\160\008@\000u@@\160\238\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\005H\128\t\006\129Po\208\000\018@@ \002\018\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\008\132\019a\018\192\000\n\000\128\000\007D\000\n\014\224\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128\001\016\130l\"X\000\001@\016\000\000\200\128\001@\220\000\000\000\000\164\000\004\003\000\1607h\000\025 \000\001\008\004\016\000\000\018\000\004B\t\176\137`\000\005\000@\000\003\"\000\005\003p\000\000\000\002\144\000\016\012\002\128\221\160\000d\128\128\000\004 \016@\000\000H\000\017\008&\194%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000\n@\000@0\n\003v\128\001\146\002\000\000\016\128A\000\000\001 \000D \155\008\150\000\000P\004\000\0002 \000P7\000\000\000\000)\000\001\000\192(\013\218\000\006H\008\000\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\003\000\1607h\000\025 \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\016\012\002\128\221\160\000d\128\128\000\004 \016@\000\000H\000\017\008&\194%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000\n@\000@0\n\003v\128\001\146\002\000\000\016\128A\000\000\001 \000D \155\008\150\000\000P\004\000\0002 \000P7\000\000\000\000)\000\001\000\192(\013\218\000\006H\008\000\000B\001\004\000\000\004\128\001\016\130l\"X\000\001@\016\000\000\200\128\001@\220\000\000\000\000\164\000\004\003\000\1607h\000\025 \000\001\008\004\016\000\000\018\000\004B\t\176\137`\000\005\000@\000\003\"\000\005\003p\000\000\000\002\144\000\016\012\002\128\221\160\000d\128\128\000\004 \016@\000\000H\000\017\008&\194%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000\n@\000H4\n\003v\128\000\146\002\001\128\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000)\000\001\000\192(\013\218\000\006H\008\000\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\003\000\1607h\000\025 \000\001\008\004\016\000\000\018\000\004B\t\176\137`\000\005\000@\000\003\"\000\005\003p\000\000\000\002\144\000\016\012\002\128\221\160\000d\128\128\000\004 \016@\000\000H\000\017\008&\194%\128\000\020\001\000\000\012\136\000\020\013\192\000\000\000\n@\000@0\n\003v\128\001\146\002\000\000\016\128A\000\000\001 \000D \155\008\150\000\000P\004\000\0002 \000P7z\213p\000\169\016\001 \208*\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\004\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248<\185\018\001\000\198+\143\222\016\007\234\024\000\141b\005\004\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\002\000\000\000\000\000\000B \000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\175\193\005\200\144\008\006!\\~\240\128?P\192\004k\016('\255_\130\011\145 \018\013B\248\253\225\000~\161\128H\214(PO\254\191\007\151\"@ \024\197q\251\194\000\253C\000\017\172@\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\251\254\030\\\137\000\128c\023\199\239\024\003\245L G\177\198\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\235\240Ar$\002\001\140W\031\188 \015\2120\001\026\196\n\t\255\215\224\130\228H\004\131P\190?x@\031\168`\0185\138\020\019\255\175\193\005\200\144\t\006\161\\~\240\128?P\192$k\016h \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \000D`\155,\150\000\000P\004 \000;\160\"Pw\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\016\028\129\000\128b\020G\237\008\003\245\012\000F1\002\130\000\000\000 9\002\001\000\196(\143\218\016\007\234\024\000\140b\005\004\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \008$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128 \144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002A\160P\027\180\000\004\144\016\008\000\132\130\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\001\200\016\008\006!D~\208\128?P\192\004c\016( \000\000\002\003\144 \016\012B\136\253\161\000~\161\128\008\198 P@\000\000\000\000\000\000\000\000\000\000\016\000\000\001\000\000\128\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\136\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\002\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002@\000\128\193\006I,\000\000\128\000@\0003@D\128\140\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\002\164@\004\131@\1687\232\000\t \016\001\t\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\002\003\144 \016\012B\136\253\161\000~\161\128\008\198 P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\175\193\005\200\144\t\006\161\\~\240\128?P\192$k\016( \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\255\135\151\"@ \024\197\241\251\198\000\253S\008\017\236q\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\002\000@\000\002\000\008\000\000\000\000 \000\000\000\000\000\000\t\020`\000\000\000\000\002\001\000&\000\000\000D\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\015Z\174\000\016\002\000\000\016\000F\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\128\000 \000\000\000\000\000\002\144\000\018\013B\128\221\160\000$\128\128@\004 \016@\000\000\000\005 \000 \025\133\001\187@\000\201\001\000\160\008A \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\128`\020\006\237\000\003$\004\000\000!\000\130\000\000\000\000)\000\001 \208(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\005H\128\t\006\129Pn\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000@0\n\003v\128\001\146\002\000\000\016\128A\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002\001\128P\027\180\000\012\144\016\000\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001H\000\008\006\001@n\208\0002@@\000\002\016\008 \000\000\000\002\144\000\016\012\002\128\221\160\000d\128\128\000\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000@@\131$\148\000\000@\000 \000\016\160\"\000\006\000\000\000\000\000\000\000\000\000\000\000\128\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\002\164@\004\131@\1687\232\000\t \016\001\t\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\002\164@\004\131@\1687h\000\t \016\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\002\144\000\016\012\002\128\221\160\000d\128\128\000\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\144h\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\016\000\000\000\000\000R\000\002A\160P\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\002\144\000\016\012\194\128\221\160\000d\128\128\016\004 \016@\000\000\000\005 \000 \025\133\001\187@\000\201\001\000\160\008A \128\000\000\001\n@\000@3\n\003v\128\001\146\002\001@\016\130A\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\001 \212(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\n@\000@3\n\003v\128\001\146\002\000@\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000R\000\002\001\152P\027\180\000\012\144\016\002\000\132\002\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\008\000\016`\018\128\000\008\000\000\000\002\004\000@\000\192\000\000\000\005 \000 \024\005\001\187@\000\201\001\000\000\008@ \128\000\000\128\000 \000A\128J\000\000 \000\000\000\008\016\001\000\003\000\000\000\000\020\128\000\128`\020\006\237\000\003$\004\000\000!\000\130\000\000\002\000\000\128\001\006\001(\000\000\128\000\000\000 @\004\000\012\000\000\000\000R\000\002\001\128P\027\180\000\012\144\016\000\000\132\002\008\000\000\008\000\002\000\004\024\004\160\000\002\000\000\000\000\129\000\016\0000\000\000\000\001H\000\008\006\001@n\208\0002@@\000\002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000 \024\005\001\187@\000\201\001\000\000\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\128`\020\006\237\000\003$\004\000\000!\000\130\000\000\002\000\000\128\001\006\001(\000\000\128\000\000\000 @\004\000\012\000\000\000\000R\000\002\001\128P\027\180\000\012\144\016\000\000\132\002\008\000\000\008\000\002\000\004\024\004\160\000\002\000\000\000\000\129\000\016\0000\000\000\000\001H\000\008\006\001@n\208\0002@@\000\002\016\008 \000\000 \000\008\000\016`\018\128\000\008\000\000\000\002\004\000@\000\192\000\000\000\005 \000 \024\005\001\187@\000\201\001\000\000\008@ \128\000\000\128\000 \000A\128J\000\000 \000\000\000\008\016\001\000\003\000\000\000\000\020\128\000\128`\020\006\237\000\003$\004\000\000!\000\130\000\000\002\000\000\128\001\006\001(\000\000\128\000\000\000 @\004\000\012\000\000\000\000R\000\002\001\128P\027\180\000\012\144\016\000\000\132\002\008\000\000\008\000\002\000\004\024\004\160\000\002\000\000\000\000\129\000\016\0000\000\000\000\001H\000\008\006\001@n\208\0002@@\000\002\016\008 \000\000 \000\008\000\016`\018\128\000\008\000\000\000\002\004\000@\000\192\000\000\000\005 \000 \024\005\001\187@\000\201\001\000\000\008@ \128\000\000\128\000 \000A\128J\000\000 \000\000\000\008\016\001\000\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\002\144\000\016\012\194\128\221\160\000d\128\128P\004 \144@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000@3\n\003v\128\001\146\002\001@\016\130A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000)\000\001\000\204(\013\218\000\006H\008\005\000B\t\004\000\000\000\000R\000\002\001\152P\027\180\000\012\144\016\002\000\132\018\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\001H\000\008\006a@n\208\0002@@(\002\016H \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\164\000\004\0030\1607h\000\025 \004\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\004\000\128\000\004\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\144j\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\019\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\002\000\002@\000\000\000\000\000\000\000\128\000 \000\000\000\000\000\000\000\004\000\004\128\000\000\000\000\000\000\001\000\000@\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000 \004\000\000 \000\140\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000@\000\016\000\000\000\000\000\001H\000\t\006\161@n\208\000\018@@ \002\016\008 \000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000:\213P\000\128\016\000\000\000\002\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000@\000\016\000\000\000\000\000\001H\000\t\006\161@n\208\000\018@@ \002\016\008 \000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248 \185\018\001\000\198+\143\2220\007\234\024\000\141b\005\004\000\000\000\000\000\000\000@ \000\000\000@\000\000\000\136\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\175\193\005\200\144\008\0061\\~\241\128?P\194\004k\016+0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\"0M\150K\000 (\002\018\000\029\208\016(;\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\008\000\002\000\000\000\000\000\000)\000\001 \212(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\004\000\128\000\004\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\128\000\144j\020\006\237\000\001$\004\002\000!\000\130\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\128@\000\000\000\128\000\000\001\016\000\000\001\136\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\191\004\023\"@$\026\133q\251\198\000\253C\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\016\\\137\000\128c\021\199\239\024\003\245\012 F\177\002\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\002\164@\004\131@\1687\232\000\t \016\001\t\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\0010\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\245\170\224\001\000 \000\001\000\004`\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\002\000\000\128\000\000\000\000\000\n@\000H5\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\214\170\128\004\000\128\000\000\000\016\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\002\000\000\128\000\000\000\000\000\n@\000H5\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\191\004\023\"@$\026\133q\251\198\000\253C\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@ \016\000\000\000 \000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\255\215\224\130\228H\004\131P\174?x\192\031\168`\0185\136\020\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000L\002\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000@\000\000\000\000 9\002\001\000\196(\143\218\016\007\234\024\000\140b\005\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\002\000\000\000\000\000\000\000\000\000@\000\127\247\252 \185\026\0010\212/\143\2220\015\234\152L\143c\173f\000\000\000@r\004\002\001\136Q\031\180 \015\2120\001\024\196\n\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\175\193\005\200\144\008\0061|~\240\128?P\192\004{\028h \000\000\000\000\000\000\002\001\000\000\000\000\000\000\000\000@\000\000\000\015\254\191\004\023\"@ \024\197\241\251\194\000\253C\000\017\236q\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \016\008\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\235\240Ar$\002A\168_\031\188 \015\2120\t\030\199\026\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\175\193\005\200\144\t\006\161|~\240\128?P\192${\028h \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\008\000\015\254\191\004\023\"@ \024\197\241\251\194\000\253C\000\017\172P\160\128\000\000\000\000\000\000\008\004\001\000\000\000\000\000\000\001\000\000 \000?\250\252\016\\\137\000\128c\023\199\239\008\003\245\012\000F\177B\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\001\000\128 \000\000\000\000\000\000 \000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\191\004\023\"@$\026\133\241\251\194\000\253C\000\145\172P\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\019\000\000\000 \000\000\000\002\000\000\000\000\000\000\000@\001\128\128\000\000\000\000@\000\000 \000\001\000\023\255_\130\011\145 \016\012b\184\253\225\000~\161\128\008\214 P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\016\012\004\000\000\000\000\002\000\000\001\000\000\008\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248 \185\026\0010\212+\143\222\016\015\234\024\004\141b%\006\255\235\240Ar$\002\001\140W\031\188 \015\2120\001\026\196\n\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\255_\130\011\145\160\019\013B\184\253\225\000\254\161\128H\214\"P`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\008\000\015\254\191\004\023\"@$\026\133\241\251\194\000\253C\000\145\172P\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\002\001\000\000\000\002\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\253~\008.D\128H5\n\227\247\140\001\250\134\001#X\129A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\239\215\224\002\164H\004\003\000\1687x\000\025 \000\005\136\020\016\000\000\000\001H\002\t\006\129@n\208\000\018@@ \002\016\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000=\250\252\000T\137\000\128`\021\006\239\000\003$\004\000\000\177\002\130\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000\008\001\000\000\008\000 \000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\001 \212(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000z\213p\000\128\016\000\000\128\0020\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013B\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002`\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131P\1607h\000\t \016\001\008\004\016\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007Z\170\000\016\002\000\000\000\000@\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\002\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002A\168P\027\180\000\004\144\016\008\000\132\002\008\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\008\000\015~\191\000\021\"@ \024\005A\187\192\000\201\001\000\000,@\160\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \000@`\131$\150\000@@\000$\000\024\160 @F\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131P\1607h\000\t \016\001\008\004\016\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000\008\001\000\000\008\000#\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\000\001 \212(\013\218\000\002H\008\004\000B\001\004\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000*D\000H4\n\131~\128\000\146\002\001\000\016\144A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\019\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H5\n\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000u\170\160\001\000 \000\000\000\004\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000$\026\133\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\128\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\016\000\000\001\0010\000\000\002\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\128\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\008@\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248 \185\018\001\000\198+\143\222\016\007\234\024\000\141b\005\004\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\031\253~\008.D\128H5\n\227\247\132\001\250\134\001#\216\195A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\004 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000_\253~\008.D\128@1\138\227\247\132\001\250\134\000#X\129A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\245\248 \185\018\001\000\198+\143\222\016\007\234\024\000\141b\005\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\128\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\n\003v\128\000\146\002\000\000\016\128A\000\000\000\000\000\004\000\000\000\000\000\000\000\004\000\000\000\000\000\000\001\000\000\000\000)\000\001 \208(\013\218\000\002H\008\000\000B\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 9\002\001\000\196(\143\218\016\007\234\024\000\140b\005\004\000\000\000\000\000\016\000\000\000\000\000\000\000\016\000\000\000\000\000\000\004\000\000\000\128\228\008\004\003\016\162?h@\031\168`\0021\136\020\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\003\144 \016\012B\136\253\161\000~\161\128\008\198 P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\008\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000@\000\000\000\000\000\000\000@\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\253~\000 \004\000\000 \000\128\001\000\000\002\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\008\000\000\000\000\000\000\002\255\235\240\001\000 \000\001\000\004\000\008\000\000\016\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\175\192\004\000\128\000\004\000\016\000 \000\000@\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\004\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\002A\160P\027\180\000\004\144\016\000\000\132\002\008\000\000\000\000\000 \000\000\000\000\000\000\000 \000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\ p\132D\144!\000\128\000\018\000\005P\144\000&\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000\028!\017\004\008@ \000\004\128\001T$\000\t\128\000\015Z\174\0008B\000\008\016\128@\000\t\000\002\168H\000\019\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000 \008\004\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\128 \000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\008\000\000\000 \000\001\000@\000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\002\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\008\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\173W\000\028!\016\004\008@ \000\004\128\001T$\000\008\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\181\\\000p\132\000\016!\000\128\000\018\000\005P\144\000\"\000\000\000\004\000\000 \008\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\008\000\000\000 \000\001\000@\000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\016\004\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\128 \000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000 \000\001\000@\000\000\000\000\000\004\000\000 \001\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000 \008\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\008\000\000@\016\000\000\008\000\000\001\000\000\008\000@\000\004\000\000\000\016\000\000\128 \000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000@\000\002\000\128\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\192\002\000@\000\002\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\128\015Z\174\000\016\002\000\000\016\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\008\000\000@\016\000\000\008 \000\000\000\000\008\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000@\000\002\000\128\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\128\000\000\002\000\000\016\004\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\001\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\0020\000\000@\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\016\004\000\000\000\016\000\000\000\000\002\000\016\000\000\000\000\000\004\000\000 \008\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\004\001\000\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000 \008\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000@\000\002\000\128\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\016\004\000\000\000\008\000\000\000\000\002\000\016\000\000\000\000\000\004\000\000 \008\000\000\004\128\000\000\128\000\004\000 \000\002\000\000\000\008\000\000@\016\000\000\000\000\000\000\000\000\008\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000 \000\001\000@\000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\004\000\000\000\016\000\000\128 \000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\008\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000@\000\000\000\000 \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\128 \000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000 \000\000\000\128\000\004\001\000\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000@\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\001\000@\000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\008\002\000\000\000\008\000\000\000\000\001\000\008\000\000\000\000\000\002\000\000\016\004\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\214\235\128\006\000\128\000\004 \016\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\002\000\000\016\004\000\000\000H\000\000@\000\002\000\016\000\001\000\000\000\004\000\000 \008\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\030\183\\\0000\004\000\000!\008\128\000\000\000\002\000\016\000\000\000\000\000\004\000\000 \008\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\001\000@\000\000\000\000\000\000\000\000 \001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000 \008\000\000\004\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\016\000\000\128 \000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\235U\194\007\008DI\002\016\008\000\001 \000U\t\000\002`\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000$\026\007\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000$\026\005\001\187@\000I\001\000\128\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\024\128\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\004\131@\1607h\000\t \000\001\008\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000A\000\000\000\000\000\005 \000$\026\005\001\187@\000I\001\000\000\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\255\132\023\"@$\030\135q\251\194\000\253S\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\191\225\005\200\144\t\007\161\\~\240\128?T\194$k\016+3\191}\192\008\001\000\000\000\000 \000\000\000\000\008\000\000\000\000\000\000$Q\128\000\000\000\000\000\004\000\000\000\000\000\016\000\000\000\000\000\014\253\247\000 \004\000\000\000\000\128\000\000\000\000 \000\000\000\000\000\029\251\238\000@\008\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\001\"\140\000\000\000\000\000\000 \000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\020`\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\018(\192\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000$Q\128\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000H\163\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005 \000 \025\133\001\187@\000\201\001\000\160\008@ \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\239\223\240\002\000@\000\002\000\008\000\000\000\000\"\000\000\000\000\000\000\t\020`\000\000\000\000\002\000\000\000\000\000\000\004\000\000\000\000\000\007\255_\130\011\145 \016\012b\184\253\225\000~\161\128\008\214 P@\000\000\000\000\000\000\004\002\000\000\000\000\000\000\000\008\128\000\000\012@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@ \016\000\000\000\000\000\000\000D\000\000\000b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\255\215\224\130\228H\004\131P\174?x@\031\168a\0185\136\021\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\012@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\128\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\003\214\171\128\004\000\128\000\004\000\017\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\136\000\030\181\\\000 \004\000\000 \000\140\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\128\001\235U\192\002\000@\000\002\000\008\192\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000?\250\252\016\\\137\000\144j\021\199\239\008\003\245\012\002F\177\006\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\1380\000\000\000\000\001\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\002\001\000\128\000\000\000\000\000\000\002 \000\000\003\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\191\004\023\"@$\026\133q\251\194\000\253C\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\002`\000\000\004\000 \000\000\0001\000\000\000\000\000@ \008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n@\000H4\014\003v\128\000\146\002\001\000\016\128A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\018\013\002\128\221\160\000$\128\128@\004 \016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\012@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\251\254\016\\\137\000\144z\029\199\239\008\003\245L\"F\177\002\179\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\254\255\132\023\"@$\030\133q\251\194\000\253S\008\145\172@\172\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000?\251\254\016\\\137\000\128c\021\199\239\008\003\245L F\177\002\179\000\000\000\000\000\000\000 \016\000\000\000\000\000\000\000D\000\000\000b\255\239\248Ar$\002\001\140W\031\188 \015\2130\129\026\196\n\204\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\255\191\225\005\200\144\t\006\161\\~\240\128?T\194$k\016+7\255\127\194\011\145 \016\012b\184\253\225\000~\169\132\008\214 V`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\008\004\000\000\000\000\000\000\000\017\000\000\000\024\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\247\252 \185\018\001 \212+\143\222\016\007\234\152D\141b\005f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\255\223\240\130\228H\004\131P\174?x@\031\170a\0185\136\021\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\255\127\194\011\145 \018\013B\184\253\225\000~\169\132H\214 V`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\001\136\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\255\127\194\011\145 \018\013B\184\253\225\000~\169\132H\214 V`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\008\004\000\000\000\000\000\000\000\017\000\000\000\024\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\127\247\252 \185\018\001 \212+\143\222\016\007\234\152D\141b\005f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\019\000\000\000 \001\000\000\000\001\136\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\004\128\000\000\000\000\000\000\000\001\004\224\006\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000 \000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\001\002\000\000\000\000\000\000\002\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\004\008\000\000\000\000\000\000\008\000\000\000\016\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\004\000\128\000\000\000\000\002\000\000\008\016\000\000\000\000\000\000\016\000\000\000 \000\000\000\000\128\001\000\001\000\000\000\000\000\000\000\008\192\008\000\016\n\000\000\000\000\000\008\000\000 @\000\000\000\000\000\000@\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\016\000\016\000\000\000\000\000\000\000\140\000\128\000\000\160\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\004\000\000\000\000\000\000\000\000\000'\0000\000\000 \000\000\000\004\000\008\000\000\000\000\000\000\000\000\000F\000`\000\000@\000\000\000\008\000\016\000\000\000\000\000\000\000\000\000\140\000\128\000\000\128\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\0020\002\000@\002\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000#\000 \000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\001\024\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\001\000\000\000\000\000\000\000\000\000\008\192\012\000\000\008\000\000\000\001\000\002\000\000\000\000\000\000\000\000\000\017\128\016\000\000\016\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000#\000 \000\000 \000\000\000\000\000\008\000\000\000\000\000\000\000\000\000F\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")
let action =
- ((16, "\000r\000r\000\000\000\000\000\211\000\000\000\000\000\000\000r\000\000\000m$\152\000\000\000<=,\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\000\018\000\000$\152\"\212\024z\000\016%\018\000\000\000\000\000\000\000\000\021>\000\130\024z\000m\024z\000\000\000`\000\000\024z\000\000\000m\000\000\000\000\001\0203,\000\000\000\0004\208\000\0005~\001.3,3,\016X\016X5~\000\0007,\000\0007\1723,\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0005\2543,\000\000\000\0005\254\000\0005\254\000\0005\254\000\000\000\000\000\000\018\160\000m\000\000\016X\000\000*\2083,\022\2263,\000\000\000\000\000\000\000\000\000\000\000\000\025\1763,\000\000\026\1563,\026\2423,\027\2223,\000\0003,\000\0003,\02843,\029 3,\029v3,\030b3,\030\1843,\000\1783,\000\000\000\000\000\000\000\000\000\0003,\031\1643,\031\2503, \2303,\000\000\000\0003,\000\000\"\168$\222\000\000\000\000\000\182\000\000\000\000\000\000\024\026\000\000\000\000\000\000\000\000\000\000\025r\000<\000\000$\222\000\000\000\166\016X\000\0003,\000\222\000\000\000\000\000m\000\000\000\000\000\000\000\000\001\030\000\000\000\000\002.\000\000\000\0113,\000\000\000\011\000\000\000\000\016X\002f\000\000\002\204\000\000\000\000\000\000\000\000\000\000\000\000\000\0008,3,\000\0008,\000\0008,8,\000\000\000\000'\"\000m\000\000\016X\003\020\000\0003,\003\018\000\000\000\000\000m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016X\003>7,\000\000\000\000<\1523,\000\0003,\000\000\000\000\003\132\000\000\000p6\172\004B3,\004\018\000\000\000\0007,\000p\000\000\000\000\000\000\000\000\000\000'\1647,>B7,>\1427,>\2187,\000\0007,\000\0007,?&7,?r7,?\1907,@\n7,@V3,\003\2287,\000\0007,@\1627,@\2387,A:\003\208\000\000\004 \000\000\000\138$\152\000\000\000\138\000\000\000\000\00423,\000\000\004\166\000\0007,\004\246\000\000\016X\004T\000\000\000\000\004T\000\000\000\000\001\020\000\000\005(\000\000$\222A\204\005N\005L\000m\004\194\005tC\018\001\148\000\000\000\000\002\028C:\000\000\000\000\000\000\005x\005l\001$\005~C\018\002\\C\018\000\000\000\000\001\"\000\000\000\000\004\238\000\000\005\018\005\198C\018\005@\000\000\000\000\002\028\000\000\005X\006,\000\000C\218\026P\000\000\000m\006.\000\000(\250\000m\006B\000\000\000\000#\158\024z\005p\000\000\005\234\000\000\005z\000\000\001*$\152\000\000$\152\000\000\005h\000\000\001*\000\000\012\166\016\n\0064C\018\005\136\006X\000\000$\152\000\004\000\000\006\\\000\000\000\000\000\000\000\000\000\000\000\000\006@3,\005\148\016\252\006F3,\005\154\006D\002\012\005\212\006R\000\0008\1729,\016X\005\178\000\000\005\1829,\000\000\000\000\000\000\000\000\000\000\000\000\000\0009\1723,\000\0009\172\000\0009\1729\172\000\000\000\000\022\140\000m\000\000\016X\005\198\000\0003,\005\208\000\000\000\000\000m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000%\1843,\000\0003,\000\000\005\224\000\000\000\011\000\000\000\000\000\000\000\000\000\000+&9,,\0089,,^9,-@9,\000\0009,\000\0009,-\1509,.x9,.\2069,/\1769,0\0063,\006\0149,\000\0009,0\2329,1>9,2 \016X\005\236\000\000\000\0003,\000\000\006\188\000\000\001B\002\134\000\000\006R\006R\001B\000\000\001B\000\000\012\166\006R\006R\000\000\000\000\000\000\020\162\000\000\000\000\000\000\000\000\006\1583,\005\242\016\252\017\190\000m\006\194\000\000\006\1663\208\006\2123\208\006\2163,\006\014\016\252\016\252\003\170\002\244\001\"\000\000\000\000\000\000\002\244\000\000\003\146\001\128\000\000\000\000\006\020\000\000\000\000\000\000\006\234\000\000\006\236\000\000\000\000\007\028\006\2383,\006F\007\022\000\000\018\246\007\000\016X\006T\016\252\000\000\000\000\006|\000\000\000\011\000\000\003\202\000\000\001B\000\000\000\000\006\206\000\000&X\016\n\007\020C\018\006h\007R\000\000\000m\000\000\001\2083\208'\238\000\000:,3,\006\154\000\000\016X\006\156\000\000\006\158\000\000\000\000\000\000\000\000\000\000\000\000\000\000:\1723,\000\000:\172\000\000:\172:\172\000\000\000\000C\184\000m\000\000\016X\006\162\000\0003,\006\160\000\000\000\000\000m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016X\006\166;,\000\000\000\0003,\000i3,\006\188\006\240'\238(\178&\134\007j3\208\0076\000\000\000\000\000m\006\248'\238\000\000\006\244'\238\000\000\000\000\015x;,\019\250;,#\012;,)H;,\000\000;,\000\000;,*\012;,5P;,6~;,8\254;,9~;,9\254;,:~;,<\214\000\000\000\000\006\202\000\000\006\218)v\000\000*:\006\222*:2~\006\224*:\000\000\000\000\000\000\000\000\000\000\007\008'\238\000\000\000\000\006\218\000\000\007\176\000\000\000m\000\000\000\186\007\178\000\000\006p\007\144\000m\006\246\007\182C\018\007\n\000p\000\0003\208\007\230\000\000\000_\005\166\007h\007\208C\018\007$\007\244\000\000\002\1403\208\007\250\000\000\007\252\000\000(\250\000m\00363\208\007\254\000\000\008\000\000\000\011b\0009\000\000\011b\000\000\000\000\019\164\004z3\208\008\002\000\000\008\004\000\000\000\000\0076\007\214\000m\007J\007\252C\018\007R\002\016\000\0003\208\008\"\000\000\003H\000\000\000\000\007\150\000\000\011b\000\000\008\006\016X\007^\0080\000\000\000\022\000\000\008\018C\018\007h\0088\000\000\004\1523\208\008>\000\000\008@\000\000(\250\000m\004\1723\208\008D\000\000\008F\000\000\000\000\000\000\007\150\000\000\000\000\000\008\000\000\006R\000\000\000\254\000\000\000\000\001\030\017\190\000\000\001\030\000\000\000\000\007|\000\000\000\011\000\003\016\252\000\000\003\202\0009\003\202\000\000\000\008\000\000\006R\000\000\006R\000\000\000\000\000\000\007~\000\000\000\000\007\140\000\000\002\146\005\014\001\012\003\202\000\000\000\000\000\000\001\210\000\000\006R\000\000\002\146\000\000\000\000\014n\005\002\012\166\000\000\012\212\000\000\008\218\012\166\000\000\000\000\008\218\000\000\000\000\007\138\000\000\000\000\007\144\000\000\003j\006R\000\000\003j\000\000\000\000\008\002\000\000\000\008\000\000\006R\000\000\000\000\000\000\015 4P\000\000\008d\000\000\015 \008f\000\000\008j\000\000&X\000m\003>\000\0003\208\008n\000\000\008X\008J\000m\007\200\008zC\018\007\220\003\248\000\0003\208\008\172\000\000\000_\004\202\000\0003\208\008\180\000\000(\250\000m\005\012\000\0003\208\008\184\000\000\004$\015 \000\000\019\164\005\176\000\0003\208\008\202\000\000\000\000\000\000\008\172\008\170\000m\008\018\008\194C\018\008\022\005\184\000\0003\208\008\240\000\000\000X\000\000\008\210\016X\008&\008\246\000\000\000\148\000\000\005\216\000\0003\208\008\254\000\000(\250\000m\005\240\000\0003\208\t\004\000\000\004$\000\000\000\000\008<\000\000\000X\015\016\008\176\000\000\000\000\000\000\008\186\000\000\001N\002\134\000\000\012\166\t\022\000\000\000\0003,\008\140\006R\000\000\008b\000\000\002\012\000\000\000\000\003V\012\166\000\000\012\166\000\000\008P\000\000\003V\000\0007,\003\1667,\000\0007,\000\000\008R\000\000\003\166\000\000\016\252\003\190\016\252\000\000\016\252\000\000\008V\000\000\003\190\000\0007,\003\166\008X\000\000<\028\000m\004\018<\028\000\000<\028\000\000\008Z\000\000\004\018\000\0007,\003\166\008^\000\000\000\000\021\230\000\000\000\000\000\000\000\000\000\000\025\020!\130\000\000\003<\000\000\004\128\000\000\000\000\008\158\000m\000\000\000\000\000\000\002\138\004\128\000\000\002\146\003\184\003\184\000\000\000\179\003\184\000\000\008v\000\000\000\000\000\000\000\000\000\000\000\000\008\242\000\000\"L\000\000$\152\004\128\000\000\003n\004\128\000\000\t\002\000\000\004\128\t\006\000\000\007\202\012\192\t\n\000\000\t\012\000\000\t\190\012\192\004\128\008\164\004\128\t\"\000\000\t$\000\000\t*\000\000$\152\000\000\003d$\152\000\000\008\180\0032\000\000\000F\004\128\000\000\004\138\004\128\000\000\002\222\001\216\000m\000\000\000\204\000m\000\000\008\194\000\000\000\000\000\000\000\000\tB\000\000\004\128\004\128\tJ\000\000\tR\000\000\004\128\tT\000\000\004\128\t\\\000\000\t6\004\128\tb\000\000\004\174\021:\004\128\t\008\004\128\t\150\000\000\t\152\000\000\000\000\004\164\004\128\000\000\003t\002n\002n\000\000\000\000\000\000\004d\002n\000\000\t \000\000\000\000\000\000\000\000\004\128\000\000\004\184\004\128\000\000\004\"\002\208\000m\t$\000\000\000\000\000\000\000\000\t\160\000\000\t\162\000\000\004\128\t\180\000\000\0076\004\128\t\182\000\000\t\186\000\000>\028\tl\t\150\008~\004\128\t\194\000\000\000\000\t\196\000\000\t\156>\028\004\128\t\202\000\000\004\128\t\204\000\000\t\206\000\000\008\244\tZ\004\128\t\212\000\000\t\214\000\000\000m\tR\000\000\000\000\021\230\000\000\000\000\0026\n,\000\000\000\000\001\017\000\000\000\000\000\0003,\001\194\nf\t\152\n\0287,\000\000\004\1627,\000\000\tx\000\000\000\000\000\000\000\000\000\000\002\134\000\000\001\013\000\000\000\000\000\000\003\202B~\001zB~B~\001z\000\000\000\000\005\242\005\242\005\242\005\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000<\152\006p\013\232\0009\000\000\000\000\003H\000\000\007\150\000\000\000\000\001\194\000\000\000\000\t\192\000R\n4Dz\000\000\004\178E\024\000\000\000\000\n>\n0\000m\000\000\000m\000\000\004\178\000\000\004\180Dz\000\000\000\000\t\160\nR\006R\t\166\000\000\0076\003H\000\000\007\150\000\000\000\254\002\132\000\000\000\000\n>\000\000\000\000\0026\000\000\004\002\000\000\000\000\000\0003,\001\194\000\000\002\134\000\000\0040\000\000\000\000\000\000\005\014\n\030\005\208\n\030\000\000\006R\n\030\000\000\005\208\000\000\006R\000\000\006R\000\000\006R\000\000\000\000\000\000\000\000\000\000\001\194\000\000\006R\000\000\005\208\000\000\006R\000\000\003\134\000\000\000\000\008\218\n\138\000\000\000\000\008\218\000m\003\020\nf\002p\000\000\002p\n\144\000\000\n\146\000\000\n\148\000\000\000\000\002\216\002p\012\164\002p\000\000\000\000\006\232\t\170\000\000\008,\t\014\n\164\tp\n\164\000\000\000\000\nP\000m\000\000\005D\t\254\000\000\000\000\000\000\001\230\000\000\t\176\000\000\000\000\000\000\008,\t\014\nP\005D\001\230\t\178\000\000\000m\000\000\n\176\n\176\t\254\000m\nR\000\000"), (16, "\n\141\n\141\n\141\n\141\n\141\n\141\n\141\n\141\n\141\n\141\n\141\000\182\n\141\n\141\n\141\n\141\n\141\n\141\n\141\n\141\n\141\020\011\020\015\020c\020g\n\141\020\019\008\002\020k\n\141\000\210\n\141\n\141\n\141\001.\008\022\n\141\011\174\001:\n\141\n\141\t*\n\141\000.\006\018\016:\016b\016\138\016\154\016\198\t*\n\141\000\023\000\027\n\141\n\141\017F\012\158\000\162\008\002\n\141\n\141\n\141\nA\n\141\000\162\011-\008\022\002\242\n\141\0055\n\141\n\141\n\141\n\141\n\141\0066\nF\000\146\n\141\n\141\n\141\n\141\n\141\n\141\000\006\n\141\n\141\n\141\n\141\015R\000\n\001.\n\141\n\141\011\174\001:\011-\011-\011F\000:\t6\011\154\n\141\n\141\n\141\n\141\n\141\n\141\n\141\000\014\n\141\005\197\n\141\000\162\n\141\000z\002\242\n\141\n\141\015n\000~\001.\000\162\n\141\0016\001:\013F\n\141\011-\011-\n\141\000\174\t6\011-\n\141\n\141\n\141\n\141\n)\n\141\n\141\004\158\005\157\nI\n\141\n\141\n\141\007\213\n\141\018\014\n\141\n\141\000\162\n\141\001.\n\141\n\141\011\174\001:\n\141\n\141\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\012\158\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\011\158\005=\003\218\000\162\005\205\008\006\008\002\005\242\005\205\005\157\005\205\005\205\005\205\0055\008\022\005\205\0055\000\194\005\205\000\222\0055\005\205\0055\005\197\003\233\001.\0055\0055\011\174\001:\005\205\005e\005e\013\"\005\149\000\250\002\026\nI\013\022\005\205\005\205\nI\nI\005\205\005\205\002\174\000\210\000\210\005\205\003i\005\205\005\205\005\205\005\205\005\205\011f\000\162\002r\005\205\005\205\005\205\005\205\005\205\005\205\0186\005\205\005\205\005\205\005\205\006\229\005\250\nI\005\205\005\205\000\162\000\162\002b\nI\n\025\002\190\t6\0055\005=\005\205\005\205\005\205\005\205\005\205\005\205\000\146\005\205\008\162\005\205\000\210\005\205\n)\t*\005\205\005\205\003\233\005=\006\229\006\229\005\205\005=\008\002\006\229\007\t\005\189\002\222\005\205\007\t\005J\008\022\005\205\005\205\005\205\005\205\018*\005\205\005\205\000\162\0055\003\233\005\205\005\205\005\205\012Z\005m\015\218\005\205\005\205\005\237\005\205\005\237\005\205\005\205\005\237\008\154\005\205\005\205\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\002U\000\162\005\237\020\030\002U\022f\005\237\019\250\005\237\005\237\005\237\008\n\tr\005\237\021w\t6\005\237\005\237\022\238\005\237\005\237\005\237\021{\005\237\005\237\n)\005\237\022j\005\237\018\214\011f\005\237\021~\022n\003\233\005\229\005\229\005\237\005\237\005\237\005\229\005\237\005\237\008\014\012^\005\237\005\237\019\250\005\237\0176\005\237\005\237\005\237\006z\004\217\013\150\005\237\005\237\005\237\005\237\005\237\005\237\015\242\005\237\005\237\005\237\005\237\005E\005.\nq\018\218\005\237\005U\006\021\0055\022\142\000\162\005\237\019\"\007\217\002\234\005\237\005\237\005\237\005\237\005\237\005\237\018&\005\237\022v\005\237\005\237\005\237\0055\014B\005\237\005\237\005\237\007\217\014F\005V\005\237\0055\014J\002y\005\237\011\206\007\217\005\237\003\014\n)\006\005\005\237\005\237\014~\005\237\017\002\005\237\005\237\t*\022~\016\026\005\237\017*\011f\000\162\0055\006\021\008\002\005\237\005\165\005\237\002b\005\237\005\237\015\198\008\022\005\237\005\237\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\012\158\000^\020r\000b\006N\000f\000j\000n\006R\020z\003\022\016B\018\210\014\022\006V\006\005\022\158\011-\000r\017\018\000\226\006f\006\130\016j\0055\006\134\008\158\022\150\000v\007\217\005]\007\242\022^\nQ\016\"\001.\005\253\0055\011\174\001:\000\238\011\238\007\217\008\002\017:\014\130\003j\003v\011-\008*\006\142\008\022\t6\008.\013R\003!\000\210\014\174\001\"\011f\001&\003\197\000\134\t2\0086\016\166\000\162\003\170\006\162\001.\008:\006\166\008>\001:\016J\006\170\006\174\008B\006\178\008=\011-\011-\017\246\008F\000\162\011-\016r\017\138\005\173\n!\005\253\017\n\005\133\006\182\006\186\008J\008N\006\190\008R\019\030\000\162\008\154\008f\003\210\003\161\008\186\014\246\008r\006\198\003\001\017\014\008=\008=\005\245\018\158\003\226\008=\t6\003\234\017\018\008\146\002\253\n)\006\013\008\150\008\210\003\197\t>\016\174\006\202\008\214\004j\005}\017\014\006\206\003\197\003\197\n)\014\178\004\142\003\197\008\222\017\018\006\210\005\141\005\245\005\245\n)\018^\001j\005\245\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\014\198\000^\020r\000b\006N\000f\000j\000n\006R\020z\000:\021\151\021\155\na\006V\006\013\021\159\004\150\000r\005\181\000\226\006f\006\130\007\029\005u\006\134\nY\004\182\000v\000\162\004\194\007\242\004\206\014\226\021\187\021\191\ni\008\002\007\029\021\195\000\238\012\"\017\030\008\002\004\218\008\022\004\230\004\250\018\234\008*\006\142\008\022\000\162\008.\013\154\n9\012\186\022\218\001\"\011f\001&\003\213\000\134\t2\0086\017\030\012\218\018\026\006\162\001.\008:\006\166\008>\001:\011f\006\170\006\174\008B\006\178\0206\018\198\014\202\005\n\008F\011f\n1\007\029\021\n\021:\005\014\019\018\005M\002m\006\182\006\186\008J\008N\006\190\008R\005\022\000\162\005\026\008f\005B\003\161\005F\005N\008r\006\198\006F\004q\t6\006J\006\029\014\230\015\006\020\146\t6\006N\015>\008\146\005r\006R\020\150\008\150\008\210\004\005\t>\004q\006\202\008\214\t*\007\029\022\226\006\206\015v\003\213\003\129\022\230\005z\008\002\008\222\005~\006\210\007\029\006\029\006\029\015\146\008\022\001j\006\029\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\005\134\000^\020r\000b\006N\000f\000j\000n\006R\020z\006F\003\129\005\154\006J\006V\005\158\005\182\020\146\000r\006N\000\226\006f\006\130\006R\020\150\006\134\005\198\005\218\000v\004q\005\226\007\242\005\234\006\007\015\n\006\030\006&\006*\015B\006>\000\238\006Z\006b\008\002\006j\006r\006v\004q\008\005\008\018\006\142\008\022\t6\008.\015z\006~\003\181\006\150\001\"\006\158\001&\003\241\000\134\0082\0086\011~\015\150\006\246\006\162\001.\008:\006\166\008>\001:\007\002\006\170\006\174\008B\006\178\007J\008\005\008\005\0115\008F\007\194\008\005\007\234\007\254\008V\008^\008n\003%\008v\006\182\006\186\008J\008N\006\190\008R\008~\000\162\008\134\008f\008\142\003\161\003%\008\202\008r\006\198\006F\008\218\008\226\006J\008\013\017\n\008\238\020\146\t6\006N\003\181\008\146\022\142\006R\020\150\008\150\008\210\003\241\t>\008\242\006\202\008\214\008\250\008\254\017\014\006\206\003\241\003\241\t\n\t\018\t\"\003\241\008\222\017\018\006\210\tF\008\013\008\013\tV\t^\001j\008\013\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\tb\000^\012>\000b\006N\000f\000j\000n\006R\019Z\t\138\004m\t\150\t\158\006V\t\242\t\254\n2\000r\003%\000\226\006f\006\130\003%\003%\006\134\017\170\004\001\000v\004m\nN\007\242\nR\nb\nj\003%\nz\n\134\011\n\011\018\000\238\011\"\011.\008\002\011J\017\014\011Z\011b\011v\008\018\006\142\008\022\000\162\008.\017\018\011\130\003\181\011\138\001\"\003%\001&\022\150\000\134\0082\0086\017\030\011\142\011\150\006\162\001.\008:\006\166\008>\001:\011\166\006\170\006\174\008B\006\178\011\186\011\194\011\198\0115\008F\011\214\011\222\011\246\011\254\012*\0122\012B\003!\004m\006\182\006\186\008J\008N\006\190\008R\012J\000\162\012N\008f\012V\012f\003!\012\138\008r\006\198\012\146\004m\012\150\012\166\0115\012\174\012\178\004a\t6\012\194\012\202\008\146\012\226\012\234\013:\008\150\008\210\000\162\t>\013\130\006\202\008\214\013\142\014\002\014\014\006\206\004a\014.\014Z\014f\017\030\014n\008\222\014\138\006\210\004a\0115\0115\014\146\014\150\001j\0115\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\014\158\000^\014\162\000b\006N\000f\000j\000n\006R\t\185\014\170\014\186\004a\017\n\006V\014\210\003\141\014\238\000r\003!\000\226\006f\006\130\003!\003!\006\134\015\018\015\"\000v\007%\003\141\007\242\017\014\t\185\015&\003!\022^\015.\0152\015:\000\238\017\018\022\182\008\002\007%\015J\015Z\015b\015f\008\018\006\142\008\022\015\130\008.\004a\015\158\005\213\015\178\001\"\003!\001&\015\194\000\134\0082\0086\019\194\015\210\004a\006\162\001.\008:\006\166\008>\001:\015\234\006\170\006\174\008B\006\178\015\250\016\006\016/\016W\008F\016\127\016\151\016\187\t\185\016\211\017\022\017R\017o\007%\006\182\006\186\008J\008N\006\190\008R\017\151\000\162\017\163\008f\017\179\017\187\n\017\003\141\008r\006\198\022F\003\141\003\141\017\206\000\162\017\194\017\215\017\223\t6\022V\017\231\008\146\018\002\003\141\003\141\008\150\008\210\017\030\t>\018B\006\202\008\214\018W\005\213\017\014\006\206\018g\005\213\005\213\007%\018o\018{\008\222\017\018\006\210\018\135\018\142\003\141\018\151\005\213\001j\007%\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\018\170\000^\020r\000b\006N\000f\000j\000n\006R\020z\005\213\018\179\018\187\018\246\006V\019*\019?\019G\000r\n\017\000\226\006f\006\130\n\017\n\017\006\134\019S\019c\000v\019k\019v\007\242\019z\019\135\019\147\n\017\019\154\019\167\019\179\019\187\000\238\019\198\019\207\019\215\019\227\019\254\022\190\020\"\020&\008*\006\142\020*\000\162\008.\021\206\005\221\020B\020\246\001\"\n\017\001&\020\254\000\134\t2\0086\017\030\021\026\021\030\006\162\001.\008:\006\166\008>\001:\021J\006\170\006\174\008B\006\178\021N\021V\021\131\022J\008F\022b\022r\022z\022\130\022\171\022\186\022\222\022\247\023\027\006\182\006\186\008J\008N\006\190\008R\023*\000\162\023.\008f\0232\003\161\023;\000\000\008r\006\198\000\000\000\000\000\000\000\000\007\241\000\000\000\000\000\000\000\000\000\000\000\000\008\146\000\000\000\000\000\000\008\150\008\210\000\000\t>\000\000\006\202\008\214\005\221\000\000\000\000\006\206\005\221\005\221\000\000\000\000\000\000\000\000\008\222\000\000\006\210\000\000\007\241\007\241\022\206\000\000\001j\007\241\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\005\221\000\000\000\000\000\000\000\000\006V\000\000\000\000\000\000\000r\000\000\000\226\006f\006\130\000\000\000\000\006\134\000\000\000\000\000v\000\000\000\000\007\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008*\006\142\000\000\000\000\008.\012\006\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\134\t2\0086\000\000\000\000\000\000\006\162\001.\008:\006\166\008>\001:\000\000\006\170\006\174\008B\006\178\000\000\000\000\000\000\011\017\008F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008J\008N\006\190\008R\000\000\000\162\000\000\008f\000\000\000\000\000\000\000\000\008r\006\198\000\000\000\000\000\000\000\000\011\017\000\000\000\000\000\000\000\000\000\000\000\000\008\146\000\000\000\000\000\000\008\150\008\210\000\000\t>\000\000\006\202\008\214\000\000\000\000\000\000\006\206\000\000\000\000\000\000\000\000\000\000\000\000\008\222\000\000\006\210\000\000\011\017\011\017\000\000\000\000\001j\011\017\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\000\000\000\000\000\000\000\000\017\n\006V\003\029\000\000\000\000\000r\000\000\000\226\006f\006\130\000\000\000\000\006\134\000\000\000\000\000v\003\029\000\000\007\242\017\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\017\018\000\000\000\000\000\000\003\029\000\000\000\000\000\000\008*\006\142\000\000\007\029\008.\013\206\000\000\000\000\t*\001\"\000\000\001&\000\000\000\134\t2\0086\017\198\008\002\007\029\006\162\001.\008:\006\166\008>\001:\008\022\006\170\006\174\008B\006\178\000\000\000\000\000\000\000\000\008F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\197\006\182\006\186\008J\008N\006\190\008R\000\000\000\162\000\000\008f\000\000\000\000\003\029\000\000\008r\006\198\003\029\003\029\000\000\000\000\000\162\000\000\007\029\000\000\000\000\000\000\000\000\008\146\003\029\000\000\000\000\008\150\008\210\017\030\t>\000\000\006\202\008\214\000\000\000\000\000\000\006\206\000\000\003\029\000\000\000\000\000\000\t6\008\222\000\000\006\210\000\000\003\029\t\197\022\150\000\000\001j\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\007\029\000^\000\000\000b\006N\000f\000j\000n\006R\000\000\000\000\000\000\007\029\000\000\006V\000\000\000\000\000\000\000r\000\000\000\226\006f\006\130\000\000\000\000\006\134\000\000\000\000\000v\000\000\000\000\007\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008*\006\142\000\000\000\000\008.\020\198\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\134\t2\0086\000\000\000\000\000\000\006\162\001.\008:\006\166\008>\001:\000\000\006\170\006\174\008B\006\178\000\000\000\000\000\000\000\000\008F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008J\008N\006\190\008R\000\000\000\162\012\158\008f\000\000\000\000\000\000\000\000\008r\006\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\146\000\000\000\000\000\000\008\150\008\210\000\000\t>\004\158\006\202\008\214\000\000\000\000\000\000\006\206\000\000\001.\000\000\000\000\011\174\001:\008\222\000\000\006\210\000\000\0002\006\022\000F\000J\001j\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\000\000\000\000\000\162\000\000\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\226\000\000\006\130\000\000\000\000\006\134\015n\000\000\000v\000\000\000\000\014N\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\005\149\000\000\014^\006\142\000\000\000\000\004\158\n\150\000\000\000\000\000\000\001\"\000\000\001&\001.\000\134\000\000\011\174\001:\000\000\000\000\006\162\001.\n\158\006\166\0016\001:\000\000\006\170\006\174\008B\006\178\000\000\000\000\000\000\000\000\000\000\n\166\000\000\000\000\000\000\000\000\000\000\n\230\n\238\000\162\006\182\006\186\000\000\000\000\006\190\000\000\n\198\000\162\000\000\n\174\000\000\n\190\000\000\000\000\000\000\006\198\000\000\000\000\000\000\0055\000\000\000\000\0055\000\000\000\000\000\000\0055\000\000\0055\000\000\000\000\n\206\0055\0055\t>\005\149\006\202\014b\000\000\000\000\000\000\006\206\000\000\000\000\000\000\000\000\000\000\000\000\014j\000\000\006\210\000\000\0002\0006\000F\000J\001j\000N\000\000\000R\000V\000\000\000Z\000\000\000^\n\214\000b\000\000\000f\000j\000n\000\000\n\182\000\000\0055\000\000\000\000\000\000\000\000\000\000\000\000\000r\000\146\000\226\004\169\000\230\000\000\000\000\000\234\000\000\000\000\000v\000\000\001.\000\000\000\000\0016\001:\000\000\n\246\n\222\000\000\000\000\000\238\000\000\000\000\000\242\000\000\000\000\000\000\000\000\000\000\001\006\001\002\001\n\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\162\000\134\000\000\000\000\0055\000\000\000\000\001*\001.\000\000\0012\0016\001:\001\142\001>\001B\000\000\001F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001J\000\000\006V\001N\000\000\000\000\000\162\000\000\000\226\006f\006\130\000\000\000\000\006\134\001V\000\000\000\000\000\000\000\000\007\242\000\000\000\000\000\000\001Z\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\001^\000\000\008b\006\142\000\000\001b\008.\000\000\003e\000\000\000\000\001\"\000\000\001&\001f\000\000\000\000\0086\000\000\000\000\001j\006\162\001.\008:\006\166\008>\001:\000\000\006\170\006\174\000\000\006\178\000\000\000\000\000\000\000\000\008F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008J\008N\006\190\008R\000\000\000\162\000\000\008f\000\000\000\000\000\000\000\000\008r\006\198\000\000\000\000\006V\000\000\000\000\000\000\000\000\000\000\000\226\006f\006\130\008\146\000\000\006\134\000\000\008\150\008\210\000\000\000\000\007\242\006\202\008\214\000\000\000\000\000\000\006\206\000\000\000\000\000\238\000\000\000\000\000\000\008\222\000\000\006\210\000\000\000\000\006\138\006\142\000\000\001j\008.\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\0086\000\000\000\000\000\000\006\162\001.\008:\006\166\008>\001:\000\000\006\170\006\174\000\000\006\178\000\000\000\000\000\000\000\000\008F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008J\008N\006\190\008R\000\000\000\162\000\000\008f\000\000\000\000\000\000\000\000\008r\006\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\146\000\000\000\000\011a\008\150\008\210\011a\000\000\000\000\006\202\008\214\000\000\000\000\000\000\006\206\000\000\000\000\000\000\000\000\011a\000\000\008\222\011a\006\210\000\000\000\000\001\130\011a\000\000\001j\000\000\000\000\000\000\011a\000\000\000\000\011a\011a\000\000\011a\011a\000\000\000\000\001\138\011a\002\182\004\001\000\000\011a\004\001\000\000\011a\000\000\011a\011a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\000\000\000\000\000\000\000\000\000\000\000\000\004\001\004\001\000\000\000\000\011a\000\000\011a\004\001\000\000\000\000\000\000\000\000\000\000\004\001\004\001\000\000\011a\004\001\000\000\004\001\000\000\002\194\004\001\000\000\000\000\004\001\000\000\004\001\004\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011a\011a\011a\000\000\011a\011a\002\198\000\000\011a\000\000\004\001\000\000\000\000\000\000\000\000\000\000\002\206\000\000\000\000\000\000\011a\000\000\000\000\011a\011a\011a\011a\004\001\000\000\000\000\004\001\011a\011a\011a\000\000\011a\011a\011a\000\000\000\000\000\000\000\000\000\000\004\001\004\001\004\001\004\001\000\000\004m\004\001\004\001\004\001\000\000\000\000\000\000\000\000\000\000\004\001\000\000\004\001\004\001\004\001\000\000\004\001\004\001\000\000\004\001\004\001\004\001\004\001\000\181\000\000\004\001\000\000\004\001\004\001\000\000\004\001\004\001\004\001\000\000\000\000\000\000\000\000\000\000\000\000\n\158\000\000\000\000\000\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\000\000\004\001\n\166\000\000\000\000\000\000\000\000\000\000\000\181\000\181\000\000\004\001\000\000\000\000\000\000\000\000\004\001\n\198\000\000\000\162\n\174\000\000\n\190\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\004\001\004\001\000\000\004\001\004m\004\001\000\000\004\001\000\000\n\206\000\000\000\000\000\000\000\000\000\000\004\001\000\000\000\000\000\000\000\000\000\000\000\000\004\001\004\005\004\001\000\000\004\005\000\000\000\000\000\000\004\001\004\001\004\001\000\000\004\001\004\001\004\001\000\000\000\000\004\005\000\000\000\000\004\005\n\214\000\000\000\000\004\005\004\005\000\000\000\000\n\182\000\000\000\000\004\005\000\000\000\000\004\005\004\005\000\000\004\005\004\005\000\000\000\181\004\005\004\005\004\005\000\000\000\000\004\005\000\000\000\000\004\005\000\000\004\005\004\005\000\000\000\000\000\181\n\222\000\000\003Q\003Q\003Q\003Q\000\000\003Q\000\000\003Q\003Q\017\n\003Q\000\000\003Q\004\005\003Q\004\005\003Q\003Q\003Q\000\000\000\000\000\000\000\000\000\000\000\000\004\005\000\170\000\000\017\014\003Q\004\005\000\000\000\000\000\000\000\000\000\000\000\000\017\018\000\000\003Q\000\000\000\000\000\000\000\000\000\000\000\000\004\005\004\005\004\005\000\000\004\005\004q\004\005\000\000\004\005\000\000\000\000\000\000\000\000\000\000\003Q\018\162\004\005\000\000\t\197\003Q\004\005\000\000\000\000\004\005\000\000\004\005\000\000\003Q\000\000\000\000\000\000\004\005\004\005\004\005\000\000\004\005\004\005\004\005\001=\001=\001=\001=\t\197\001=\000\000\001=\001=\000\000\001=\000\000\001=\000\000\001=\000\000\001=\001=\001=\000\000\000\000\000\000\000\000\016\222\000\000\000\162\000\000\003Q\001=\001=\001=\000\000\000\000\000\000\000\000\001=\000\000\000\000\017\030\001=\000\000\000\000\000\000\001=\000\000\000\000\000\000\001=\000\000\000\000\016\226\000\000\000\000\001=\000\000\000\000\000\000\000\000\t\197\000\000\001=\000\000\000\000\000\000\001=\000\000\000\000\003Q\000\000\000\000\000\000\000\000\000\000\001=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001=\000\000\000\000\001=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\181\000\000\000\000\011\181\000\000\000\000\001=\000\000\001=\000\000\001=\000\000\001=\000\000\000\000\000\000\011\181\001=\000\000\011\181\001=\000\000\000\000\006\230\011\181\000\000\000\000\000\000\000\000\000\000\011\181\000\000\000\000\011\181\011\181\001=\011\181\011\181\001=\001=\006\238\011\181\006\250\001\137\000\000\011\181\001\137\000\000\011\181\016\230\011\181\011\181\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\137\000\000\000\000\001\137\000\000\000\000\000\000\000\000\001\137\000\000\000\000\011\181\000\000\011\181\001\137\000\000\000\000\001\137\001\137\000\000\001\137\001\137\000\000\011\181\000\000\001\137\000\000\000\000\007\006\001\137\000\000\000\000\001\137\000\000\001\137\001\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\181\011\181\011\181\000\000\011\181\000\000\007\n\000\000\011\181\000\000\001\137\000\000\001\137\000\000\000\000\000\000\007\018\000\000\000\000\000\000\000\000\000\000\001\137\011\181\000\000\011\181\000\000\000\000\000\000\000\000\000\000\011\181\011\181\011\181\000\000\011\181\011\181\011\181\000\000\000\000\000\000\000\000\000\000\001\137\001\137\001\158\000\000\001\137\001\137\000\000\000\000\001\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\137\000\000\000\000\001\137\001\137\001\137\001\137\000\000\000\000\000\000\000\000\002J\001\137\001\137\000\000\001\137\001\137\001\137\004%\000\000\002\130\004%\002\134\004%\002\138\004%\000\000\004%\000\000\000\000\002\142\004%\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\004%\000\000\000\000\000\000\000\000\004%\000\000\000\000\0002\000\142\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\004%\000b\004%\000f\000j\000n\000\000\000\000\004%\000\000\000\000\004%\004%\000\000\000\000\000\000\000r\000\000\000\000\004%\000\000\000\000\004%\004%\000\000\000\000\000v\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\130\000\000\000\000\004%\000\000\000\158\000\000\004%\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000\000\004%\t\181\t\181\t\181\t\181\000\000\t\181\000\000\t\181\t\181\000\000\t\181\000\000\t\181\000\000\t\181\000\000\t\181\t\181\t\181\004%\000\000\000\000\004%\004%\000\000\000\000\004%\000\000\t\181\t\181\t\181\004%\004%\000\000\000\162\t\181\004%\000\000\000\000\t\181\000\000\000\000\000\000\016\246\000\000\000\000\000\000\016\254\002\154\000F\000J\000\166\000N\t\181\000R\000V\000\000\000Z\000\000\000^\t\181\000b\000\000\000f\t\181\000n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\181\n\249\000\000\000r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000v\000\000\000\000\000\000\000\000\000\000\t\181\000\000\000\000\t\181\000\000\000\000\000\000\001\190\000\000\000\000\002\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\181\000\000\t\181\000\000\t\181\001\202\t\181\000\000\002\001\000\000\000\134\t\181\000\000\002\001\t\181\000\000\000\000\000\000\000\000\001\210\000\000\000\000\002\001\002\001\000\000\0022\002:\000\000\000\000\t\181\002\001\000\000\017r\t\181\001\242\000\000\000\000\001\218\000\000\001\234\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\000\142\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\001\250\000^\002\001\000b\000\000\000f\000j\000n\000\000\000\000\000\000\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000v\000\000\000\000\000\000\000\000\002\001\002\002\000\000\000\000\002\001\002\001\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\000}\000\130\000\000\000}\000\000\002\001\000\158\000\000\002\001\002\001\002\001\002\001\000\000\000\000\000\134\000\000\001\202\002\001\002\001\000}\002B\002\n\002\001\000\000\000}\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000}\000}\000\000\000}\000}\000\000\000\000\000\000\000}\000\000\000e\000\000\001\242\000e\000\000\001\218\000\000\001\234\000}\000\162\000\000\000\000\000\000\000\000\000\000\000\000\000e\000\000\000\000\000e\000\000\000\000\000\000\000\000\000e\000\000\000\166\001\250\000\000\000}\001\210\000\000\000\000\000e\000e\000\000\000e\000e\000\000\000}\000\000\000e\000\000\000\000\000\000\000e\000\000\000\000\001\218\002)\001\234\000e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000}\002\002\000\000\000\000\000}\000}\000\000\000\000\001\226\000\000\000e\000\000\000e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000}\000\000\000e\000}\000}\000}\000}\000\000\000\000\000\000\000\000\000\000\000}\000}\000\000\000}\002\n\000}\000\000\000\000\000\000\000\000\000\000\000e\000e\000\000\000\000\000e\000e\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\000]\000\000\000\000\000]\000\000\000e\000\000\000\000\000e\000e\000e\000e\000\000\000\000\000\000\000\000\000]\000e\000e\000]\000e\000e\000e\000\000\000]\000\000\000\000\000\000\000\000\000\000\000]\000\000\000\000\000]\000]\000\000\000]\000]\000\000\000\000\000\000\000]\000\000\000a\000\000\000]\000a\000\000\001\218\000\000\000]\000]\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000a\000\000\000\000\000a\000\000\000\000\000\000\000\000\000a\000\000\000\000\000]\000\000\000]\000a\000\000\000\000\000a\000a\000\000\000a\000a\000\000\000]\000\000\000a\000\000\000\000\000\000\000a\000\000\000\000\001\218\000\000\000a\000a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000]\000]\000\000\000\000\000]\000]\000\000\000\000\001\226\000\000\000a\000\000\000a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000]\000\000\000a\000]\000]\000]\000]\000\000\000\000\000\000\000\000\000\000\000]\000]\000\000\000]\000]\000]\000\000\000\000\000\000\000\000\000\000\000a\000a\000\000\000\000\000a\000a\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\000q\000\000\000\000\000q\000\000\000a\000\000\000\000\000a\000a\000a\000a\000\000\000\000\000\000\000\000\001\202\000a\000a\000q\000a\000a\000a\000\000\000q\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000q\000q\000\000\000q\000q\000\000\000\000\000\000\000q\000\000\000i\000\000\000q\000i\000\000\001\218\000\000\001\234\000q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\202\000\000\000\000\000i\000\000\000\000\000\000\000\000\000i\000\000\000\000\001\250\000\000\000q\001\210\000\000\000\000\000i\000i\000\000\000i\000i\000\000\000q\000\000\000i\000\000\000\000\000\000\000i\000\000\000\000\001\218\000\000\001\234\000i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000q\000q\000\000\000\000\000q\000q\000\000\000\000\001\226\000\000\000i\000\000\000i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000q\000\000\000i\000q\000q\000q\000q\000\000\000\000\000\000\000\000\000\000\000q\000q\000\000\000q\000q\000q\000\000\000\000\000\000\000\000\000\000\000i\000i\000\000\000\000\000i\000i\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\000m\000\000\000\000\000m\000\000\000i\000\000\000\000\000i\000i\000i\000i\000\000\000\000\000\000\000\000\001\202\000i\000i\000m\000i\000i\000i\000\000\000m\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000m\000m\000\000\000m\000m\000\000\000\000\000\000\000m\000\000\000u\000\000\000m\000u\000\000\001\218\000\000\001\234\000m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\202\000\000\000\000\000u\000\000\000\000\000\000\000\000\000u\000\000\000\000\001\250\000\000\000m\001\210\000\000\000\000\000u\000u\000\000\000u\000u\000\000\000m\000\000\000u\000\000\000\000\000\000\001\242\000\000\000\000\001\218\000\000\001\234\000u\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000m\000m\000\000\000\000\000m\000m\000\000\000\000\001\226\000\000\001\250\000\000\000u\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000m\000\000\000u\000m\000m\000m\000m\000\000\000\000\000\000\000\000\000\000\000m\000m\000\000\000m\000m\000m\000\000\000\000\000\000\000\000\000\000\000u\002\002\000\000\000\000\000u\000u\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\001\190\000\000\000\000\000\133\000\000\000u\000\000\000\000\000u\000u\000u\000u\000\000\000\000\000\000\000\000\001\202\000u\000u\000\133\000u\000u\000u\000\000\000\133\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\133\000\133\000\000\000\133\002:\000\000\000\000\000\000\000\133\000\000\001\190\000\000\001\242\000y\000\000\001\218\000\000\001\234\000\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\202\000\000\000\000\000y\000\000\000\000\000\000\000\000\000y\000\000\000\000\001\250\000\000\000\133\001\210\000\000\000\000\000y\000y\000\000\000y\000y\000\000\000\133\000\000\000y\000\000\000\000\000\000\001\242\000\000\000\000\001\218\000\000\001\234\000y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\002\002\000\000\000\000\000\133\000\133\000\000\000\000\001\226\000\000\001\250\000\000\000y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\000\000\000y\000\133\000\133\000\133\000\133\000\000\000\000\000\000\000\000\000\000\000\133\000\133\000\000\002B\002\n\000\133\000\000\000\000\000\000\000\000\000\000\000y\002\002\000\000\000\000\000y\000y\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\001\190\000\000\000\000\000\129\000\000\000y\000\000\000\000\000y\000y\000y\000y\000\000\000\000\000\000\000\000\001\202\000y\000y\000\129\000y\002\n\000y\000\000\000\129\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\129\000\129\000\000\000\129\002:\000\000\000\000\000\000\000\129\000\000\000\000\000\000\001\242\000\000\000\000\001\218\000\000\001\234\000\129\000\000\000\000\000\000\000\000\000\000\t\165\t\165\t\165\t\165\000\000\t\165\000\000\t\165\t\165\000\000\t\165\000\000\t\165\001\250\t\165\000\129\t\165\t\165\t\165\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000\000\000\000\t\165\t\165\t\165\000\000\000\000\000\000\000\000\t\165\000\000\000\000\000\000\t\165\000\000\000\000\000\000\000\000\000\000\000\000\000\129\002\002\000\000\000\000\000\129\000\129\000\000\t\165\001\226\000\000\000\000\000\000\000\000\000\000\t\165\000\000\000\000\000\000\t\165\000\000\000\129\000\000\000\000\000\129\000\129\000\129\000\129\t\165\000\000\000\000\000\000\000\000\000\129\000\129\000\000\000\129\002\n\000\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\165\000\000\000\000\t\165\000\000\000\000\000\000\000\000\000\000\t\169\t\169\t\169\t\169\000\000\t\169\000\000\t\169\t\169\t\165\t\169\t\165\t\169\t\165\t\169\t\165\t\169\t\169\t\169\000\000\t\165\000\000\000\000\t\165\000\000\000\000\000\000\000\000\t\169\t\169\t\169\000\000\000\000\000\000\000\000\t\169\000\000\000\000\t\165\t\169\000\000\016\250\t\165\017v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\169\000\000\000\000\000\000\0055\000\000\000\000\t\169\000\000\000\000\000\000\t\169\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\169\004i\000\000\0055\004i\000\000\004i\000\000\004i\000\000\004i\000\000\0055\0055\004i\004i\000\000\000\000\000\000\t\169\000\000\000\000\t\169\000\000\000\000\004i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004i\004i\0055\t\169\000\000\t\169\004i\t\169\002b\t\169\000\157\0055\0055\000\000\t\169\000\000\000\000\t\169\000\000\000\000\000\000\000\000\004i\000\000\004i\000\138\000\157\000\000\000\000\000\000\004i\000\000\t\169\004i\004i\000\000\t\169\000\000\000\000\000\000\n\166\004i\0055\000\000\004i\004i\000\157\000\157\000\000\000\000\0055\000\000\000\000\000\000\004i\000\157\000\000\000\000\n\174\000\000\n\190\000\000\000\000\0055\004i\000\000\000\000\000\000\004Q\000\000\000\000\004Q\004i\004Q\000\000\004Q\004i\004Q\000\000\000\000\000\157\004Q\004Q\0055\000\000\004i\0055\0055\000\000\000\000\0055\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0055\004Q\004Q\000\000\000\000\004i\000\000\004Q\004i\004i\000\000\000\000\004i\000\000\000\157\000\000\000\000\004i\004i\000\000\000\000\n\182\004i\004Q\000\000\004Q\005\210\000\000\000\000\000\000\000\000\004Q\000\000\000\157\004Q\004Q\000\000\000\000\000\000\000\000\000\000\000\000\004Q\000\000\000\000\004Q\004Q\000\000\000\157\000\157\000\000\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004Q\0002\0006\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\004Q\000\000\000\000\004Q\004Q\000\000\000\000\004Q\000\000\017~\000r\017\154\004Q\004Q\000\000\000\000\017\166\004Q\000\000\000\000\000v\000\000\0055\000\000\000\000\0055\000\000\0055\000\000\0055\000\000\0055\000\000\000\000\017\190\0055\0055\000\000\000\000\000\000\000\000\000\130\000\000\000\000\000\000\017\234\0055\000\000\0055\000\000\000\000\0055\000\000\000\000\000\134\0055\0055\0055\000\000\000\000\000\000\0055\0055\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\n\000\000\000\000\018Z\0055\000\000\0055\000\000\000\000\000\000\000\000\000\000\002b\000\000\007M\0055\0055\000\000\018r\000\000\007\209\000\000\018~\0055\018\138\000\000\0055\0055\000\000\018\154\0055\000\000\019J\000\000\000\000\000\000\0055\000\000\000\146\000\000\000\000\007M\000\000\000\000\000\000\000\000\0055\019V\000\000\007M\000\000\019n\007M\007M\0055\000\000\000\000\000\000\0055\000\000\000\000\000\000\007M\000\000\000\000\000\000\000\000\0055\000\000\000\000\000\000\000\000\000\000\001\161\000\000\000\000\001\161\000\000\000\000\000\000\007M\000\000\000\000\000\000\0055\000\000\000\000\0055\000\000\001\161\0055\0055\001\161\007M\0055\000\000\000\000\001\161\000\000\0055\0055\000\000\000\000\001\161\0055\000\000\001\161\001\161\000\000\001\161\001\161\000\000\000\000\007M\001\161\000\000\007M\007M\001\161\000\000\000\000\001\161\000\000\001\161\001\161\007M\007M\000\000\000\000\000\000\007M\000\000\0002\tN\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\001\161\000^\001\161\000b\000\000\000f\000j\000n\000\000\000\000\000\000\000\000\001\161\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000v\000\000\000\000\000\000\000\000\001\161\001\161\0076\000\000\001\161\n^\000\000\000\000\001\161\000\000\003I\000\000\003I\000\000\000\000\003I\000\130\000\000\000\000\000\000\000\000\000\000\000\000\001\161\000\000\001\161\000\000\000\000\000\000\000\134\003I\007>\001\161\001\161\000\000\001\161\001\161\001\161\000\000\003I\003I\000\000\003I\003I\000\000\000\000\000\000\000\000\003I\000\000\003I\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003I\003I\000\000\003I\003I\003I\000\000\003I\003I\000\162\003I\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\153\000\000\000\000\011\153\000\000\003I\003I\000\000\000\000\003I\000\000\000\000\003I\000\000\000\000\000\000\011\153\000\000\000\000\011\153\003I\000\000\000\000\003Z\000\000\000\000\000\000\000\000\000\000\003I\011\153\003I\000\000\000\000\011\153\000\000\011\153\011\153\000\000\000\000\003b\003I\003n\000\000\000\000\011\153\003I\000\000\011\153\000\000\011\153\000\000\003I\000\000\000\000\003I\000\000\000\000\000\000\000\000\000\000\003I\000\000\000\000\000\000\004\018\000\000\000\000\004b\000\000\011\153\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\026\011\153\000\000\002\t\000\000\000\000\003z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\"\000\000\000\000\000\000\002\t\000\000\004r\004z\000\000\011\153\011\153\000\000\011\153\000\000\003~\004B\011\153\000\226\004*\tz\004:\000\000\t~\000\000\003\134\000\000\000\000\000\000\011\153\000\000\000\000\000\000\000\000\011\153\011\153\000\000\000\000\000\238\000\000\011\153\004J\000\000\000\000\011\153\011\153\011\153\t\130\n*\000\000\n>\nV\000\000\002\t\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\162\001.\000\000\t\166\008>\001:\000\000\t\170\t\174\004R\t\178\000\000\002\t\000\000\000\000\000\000\0042\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\182\000\000\002\t\t\186\000\000\000\000\000\162\002\t\002\t\000\000\000\000\000\000\000\000\000\000\t\194\000\000\000\000\004\130\004Z\002\t\000\000\000\000\000\000\nZ\000\226\nr\tz\000\000\000\000\t~\002\154\000F\000J\000\000\000N\t\198\000R\000V\000\000\000Z\t\202\000^\000\000\000b\000\238\000f\011R\000n\000\000\t\206\000\000\000\000\000\000\t\130\n*\001j\n>\nV\000r\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000v\000\000\000\000\000\000\t\162\001.\000\000\t\166\008>\001:\000\000\t\170\t\174\000\000\t\178\000\000\000\000\000\000\000\000\000\000\000\000\000\149\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\182\000\000\000\000\t\186\000\134\000\000\000\162\000\149\000\000\000\000\000\000\000\000\000\000\000\000\t\194\000\000\000\000\000\000\000\000\000\000\000\000\000\149\000\000\nZ\000\226\nr\tz\000\149\000\149\t~\000\000\000\000\000\000\000\000\000\000\t\198\000\149\000\000\000\000\n\174\t\202\000\149\000\162\000\000\000\238\000\000\n\254\000\000\000\000\t\206\000\000\000\000\000\000\t\130\n*\001j\n>\nV\000\000\000\000\000\000\000\149\001\"\000\000\001&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\162\001.\000\000\t\166\008>\001:\000\000\t\170\t\174\000\000\t\178\000\000\000\000\000\000\000\000\000\000\000\000\000\153\000\000\000\000\000\000\000\000\000\000\000\149\000\000\006\182\t\182\000\000\000\000\t\186\n\182\000\000\000\162\000\153\000\000\000\000\000\000\000\000\000\000\000\000\t\194\000\000\000\149\000\000\000\000\000\000\000\000\000\153\000\000\nZ\000\226\nr\tz\000\153\000\153\t~\000\000\000\149\000\149\000\000\000\000\t\198\000\153\000\000\000\000\n\174\t\202\000\153\000\000\000\000\000\238\000\000\004\201\000\000\000\000\t\206\000\000\000\000\000\000\t\130\n*\001j\n>\nV\000\000\000\000\000\000\000\153\001\"\000\000\001&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\162\001.\000\000\t\166\008>\001:\000\000\t\170\t\174\000\000\t\178\000\000\000\000\000\000\000\000\000\000\000\000\001\137\000\000\000\000\001\137\000\000\000\000\000\153\000\000\006\182\t\182\000\000\000\000\t\186\n\182\000\000\000\162\001\137\000\000\000\000\000\000\000\000\000\000\000\000\t\194\001\137\000\153\000\000\000\000\000\000\000\000\001\137\000\000\nZ\000\000\nr\000\000\001\137\001\137\000\000\000\000\000\153\000\153\000\000\007j\t\198\001\137\007\186\000\000\001\137\t\202\001\137\001\137\000\000\000\000\000\000\001\189\000\000\000\000\t\206\007r\000\000\000\000\002\017\000\000\001j\000\000\000\000\002\017\000\000\000\000\001\137\000\000\001\137\007z\000\000\000\000\002\017\002\017\000\000\007\202\007\210\000\000\000\000\000\000\002\017\000\000\000\000\000\000\007\154\000\000\000\000\007\130\000\000\007\146\002\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\137\001\137\001\150\000\000\001\137\001\137\000\000\000\000\001\137\000\000\007\162\000\000\002\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\137\000\000\002\017\001\137\001\137\000\000\001\137\000\000\000\000\000\000\000\000\002V\001\137\001\137\000\000\001\137\001\137\001\137\000\000\000\000\000\000\000\000\000\000\002\017\007\170\000\000\000\000\002\017\000\000\000\000\000\000\007\138\000\000\001%\000\000\000\000\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\017\000\000\002\017\007r\000\000\000\000\001%\000\000\000\000\002\017\002\017\001%\007\218\007\178\002\017\000\000\000\000\007z\000\000\000\000\001%\001%\000\000\001%\001%\000\000\000\000\000\000\001%\000\000\001\013\000\000\007\154\001\013\000\000\007\130\000\000\007\146\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\013\000\000\000\000\001\013\000\000\000\000\000\000\000\000\001\013\000\000\000\000\007\162\000\000\001%\007z\000\000\000\000\001\013\001\013\000\000\001\013\001\013\000\000\001%\000\000\001\013\000\000\000\000\000\000\001\013\000\000\000\000\007\130\000\000\007\146\001\013\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001%\007\170\000\000\000\000\001%\000\000\000\000\000\000\007\138\000\000\001\013\000\000\001\013\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\013\001%\000\000\001%\000\000\000\000\000\000\000\000\000\000\000\000\001%\001%\000\000\001%\007\178\001%\000\000\000\000\000\000\000\000\000\000\001\013\001\013\000\000\000\000\001\013\000\000\000\000\000\000\007\138\000\000\001\005\000\000\000\000\001\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\013\000\000\001\013\001\005\000\000\000\000\001\005\000\000\000\000\001\013\001\013\001\005\001\013\001\013\001\013\000\000\000\000\001\005\000\000\000\000\001\005\001\005\000\000\001\005\001\005\000\000\000\000\000\000\001\005\000\000\001\t\000\000\001\005\001\t\000\000\007\130\000\000\001\005\001\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000\000\000\000\001\t\000\000\000\000\000\000\000\000\001\t\000\000\000\000\001\005\000\000\001\005\001\t\000\000\000\000\001\t\001\t\000\000\001\t\001\t\000\000\001\005\000\000\001\t\000\000\000\000\000\000\001\t\000\000\000\000\007\130\000\000\001\t\001\t\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\005\001\005\000\000\000\000\001\005\000\000\000\000\000\000\007\138\000\000\001\t\000\000\001\t\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\001\005\000\000\001\005\000\000\000\000\000\000\000\000\000\000\000\000\001\005\001\005\000\000\001\005\001\005\001\005\000\000\000\000\000\000\000\000\000\000\001\t\001\t\000\000\000\000\001\t\000\000\000\000\000\000\007\138\000\000\001\025\000\000\000\000\001\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000\000\001\t\007r\000\000\000\000\001\025\000\000\000\000\001\t\001\t\001\025\001\t\001\t\001\t\000\000\000\000\007z\000\000\000\000\001\025\001\025\000\000\001\025\001\025\000\000\000\000\000\000\001\025\000\000\001\017\000\000\001\025\001\017\000\000\007\130\000\000\007\146\001\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007r\000\000\000\000\001\017\000\000\000\000\000\000\000\000\001\017\000\000\000\000\007\162\000\000\001\025\007z\000\000\000\000\001\017\001\017\000\000\001\017\001\017\000\000\001\025\000\000\001\017\000\000\000\000\000\000\001\017\000\000\000\000\007\130\000\000\007\146\001\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\025\001\025\000\000\000\000\001\025\000\000\000\000\000\000\007\138\000\000\001\017\000\000\001\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\017\001\025\000\000\001\025\000\000\000\000\000\000\000\000\000\000\000\000\001\025\001\025\000\000\001\025\001\025\001\025\000\000\000\000\000\000\000\000\000\000\001\017\001\017\000\000\000\000\001\017\000\000\000\000\000\000\007\138\000\000\001\021\000\000\000\000\001\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\017\000\000\001\017\007r\000\000\000\000\001\021\000\000\000\000\001\017\001\017\001\021\001\017\001\017\001\017\000\000\000\000\007z\000\000\000\000\001\021\001\021\000\000\001\021\001\021\000\000\000\000\000\000\001\021\000\000\001\029\000\000\001\021\001\029\000\000\007\130\000\000\007\146\001\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007r\000\000\000\000\001\029\000\000\000\000\000\000\000\000\001\029\000\000\000\000\007\162\000\000\001\021\007z\000\000\000\000\001\029\001\029\000\000\001\029\001\029\000\000\001\021\000\000\001\029\000\000\000\000\000\000\007\154\000\000\000\000\007\130\000\000\007\146\001\029\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\021\001\021\000\000\000\000\001\021\000\000\000\000\000\000\007\138\000\000\007\162\000\000\001\029\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\029\001\021\000\000\001\021\000\000\000\000\000\000\000\000\000\000\000\000\001\021\001\021\000\000\001\021\001\021\001\021\000\000\000\000\000\000\000\000\000\000\001\029\007\170\000\000\000\000\001\029\000\000\000\000\000\000\007\138\000\000\007j\000\000\000\000\001-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\029\000\000\001\029\007r\000\000\000\000\001-\000\000\000\000\001\029\001\029\001-\001\029\001\029\001\029\000\000\000\000\007z\000\000\000\000\001-\001-\000\000\001-\007\210\000\000\000\000\000\000\001-\000\000\007j\000\000\007\154\001!\000\000\007\130\000\000\007\146\001-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007r\000\000\000\000\001!\000\000\000\000\000\000\000\000\001!\000\000\000\000\007\162\000\000\001-\007z\000\000\000\000\001!\001!\000\000\001!\001!\000\000\001-\000\000\001!\000\000\000\000\000\000\007\154\000\000\000\000\007\130\000\000\007\146\001!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001-\007\170\000\000\000\000\001-\000\000\000\000\000\000\007\138\000\000\007\162\000\000\001!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\001-\000\000\001-\000\000\000\000\000\000\000\000\000\000\000\000\001-\001-\000\000\007\218\007\178\001-\000\000\000\000\000\000\000\000\000\000\001!\007\170\000\000\000\000\001!\000\000\000\000\000\000\007\138\000\000\007j\000\000\000\000\001)\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\000\000\001!\007r\000\000\000\000\001)\000\000\000\000\001!\001!\001)\001!\007\178\001!\000\000\000\000\007z\000\000\000\000\001)\001)\000\000\001)\007\210\000\000\000\000\000\000\001)\000\000\000\000\000\000\007\154\000\000\000\000\007\130\000\000\007\146\001)\000\000\000\000\000\000\000\000\000\000\000\226\000\000\tz\000\000\000\000\t~\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\162\000\000\001)\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\001)\000\000\000\000\000\000\t\130\n*\000\000\n>\nV\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\000\000\001)\007\170\t\162\001.\001)\t\166\008>\001:\007\138\t\170\t\174\000\000\t\178\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001)\000\000\001)\000\000\006\182\t\182\000\000\000\000\t\186\001)\001)\000\162\001)\007\178\001)\000\000\000\000\000\000\000\226\t\194\000\230\000\000\000\000\000\234\000\000\000\000\000\000\000\000\000\000\000\000\nr\000\000\007\246\000\000\000\000\000\000\000\000\000\000\000\238\000\000\t\198\000\242\000\000\000\000\000\000\t\202\000\000\000\254\001\002\001\n\000\000\001\201\000\000\000\000\t\206\000\000\001\"\000\000\001&\000\000\001j\000\000\000\000\000\000\000\000\000\000\001*\001.\000\000\0012\0016\001:\000\000\001>\001B\000\000\001F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001J\000\000\000\000\001N\000\000\000\000\000\162\000\000\000\226\000\000\000\230\000\000\000\000\000\234\001V\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\225\001Z\007\225\000\000\000\000\000\000\000\238\000\000\000\000\000\242\000\000\000\000\000\000\001^\000\000\000\254\001\002\001\n\001b\tv\000\000\007\225\000\000\007\225\001\"\000\000\001&\001f\000\000\000\000\000\000\000\000\000\000\001j\001*\001.\000\000\0012\0016\001:\000\000\001>\001B\000\000\001F\000\000\000\000\000\000\000\000\000\000\000\226\000\000\000\230\000\000\000\000\000\234\000\000\000\000\000\000\000\000\001J\000\000\000\000\001N\014R\000\000\000\162\000\000\000\000\000\000\000\238\000\000\000\000\000\242\001V\000\000\000\000\000\000\000\000\000\254\001\002\001\n\000\000\001Z\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\001^\000\000\000\000\001*\001.\001b\0012\0016\001:\000\000\001>\001B\000\000\001F\001f\000\000\000\000\000\000\000\000\000\226\001j\000\230\000\000\000\000\000\234\000\000\000\000\000\000\000\000\001J\000\000\000\000\001N\000\000\000\000\000\162\000\000\000\000\000\000\000\238\000\000\000\000\000\242\001V\000\000\000\000\000\000\000\000\000\254\004\210\001\n\000\000\001Z\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\001^\000\000\000\000\001*\001.\001b\0012\0016\001:\000\169\001>\001B\000\000\001F\001f\000\000\000\000\000\000\000\000\000\000\001j\000\000\000\000\000\000\000\000\n\158\000\000\000\000\000\000\001J\000\000\000\000\001N\000\000\000\000\000\162\000\000\000\246\000\000\n\166\000\000\000\000\007\233\001V\007\233\000\169\000\169\007\233\000\000\000\000\000\000\000\000\001Z\000\000\000\169\000\000\000\000\n\174\000\000\n\190\000\000\000\000\007\233\000\000\001^\007\233\000\000\000\000\000\000\001b\000\000\007\233\007\233\007\233\000\000\000\000\000\000\000\000\001f\n\206\007\233\000\000\007\233\000\000\001j\000\000\000\000\000\000\000\000\000\000\007\233\007\233\000\000\007\233\007\233\007\233\000\000\007\233\007\233\000\000\007\233\000\000\000\000\000\000\000\000\000\000\000\226\000\000\000\230\000\000\000\000\000\234\000\000\000\169\000\000\000\000\007\233\000\000\000\000\007\233\n\182\000\000\007\233\000\000\000\000\000\000\000\238\000\000\000\000\000\242\007\233\000\000\000\169\000\000\000\000\000\254\001R\001\n\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\169\000\169\000\000\000\000\007\233\000\000\000\000\001*\001.\007\233\0012\0016\001:\000\161\001>\001B\000\000\001F\007\233\000\000\000\000\000\000\000\000\000\000\007\233\000\000\000\000\000\000\000\000\n\158\000\000\000\000\000\000\001J\000\000\000\000\001N\000\000\000\000\000\162\000\000\003\222\000\000\n\166\000\000\000\000\003A\001V\003A\000\161\000\161\003A\000\000\000\000\000\000\000\000\001Z\000\000\000\161\000\000\000\000\n\174\000\000\n\190\000\000\000\000\003A\000\000\001^\003A\000\000\000\000\000\000\001b\000\000\003A\003A\003A\000\000\000\000\000\000\000\000\001f\000\161\003A\000\000\003A\000\000\001j\000\000\000\000\000\000\000\000\000\000\003A\003A\000\000\003A\003A\003A\000\000\003A\003A\000\000\003A\000\000\000\000\000\000\000\000\000\000\000\226\000\000\001\022\000\000\000\000\001\026\000\000\000\161\000\000\000\000\003A\000\000\000\000\003A\n\182\000\000\003A\000\000\000\000\000\000\000\238\000\000\000\000\000\242\003A\000\000\000\161\000\000\000\000\001\030\003\162\001\n\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\161\000\161\000\000\000\000\003A\000\000\000\000\003\026\001.\003A\003\030\0016\001:\000\000\003\"\003&\000\000\003*\003A\000\000\000\000\000\000\000\000\000\226\003A\001\022\000\000\000\000\001\026\000\000\000\000\000\000\000\000\003.\000\000\000\000\0032\000\000\000\000\000\162\000\000\000\000\000\000\000\238\000\000\000\000\000\242\003:\000\000\000\000\000\000\000\000\001\030\003\006\001\n\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\003>\000\000\000\000\003\026\001.\003B\003\030\0016\001:\000\000\003\"\003&\000\000\003*\003F\000\000\000\000\000\000\000\000\000\226\001j\001\022\000\000\000\000\001\026\000\000\000\000\000\000\000\000\003.\000\000\000\000\0032\000\000\000\000\000\162\000\000\000\000\000\000\000\238\000\000\000\000\000\242\003:\000\000\000\000\000\000\000\000\001\030\0036\001\n\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\003>\000\000\000\000\003\026\001.\003B\003\030\0016\001:\000\000\003\"\003&\000\000\003*\003F\000\000\000\000\000\000\000\000\000\226\001j\006\130\000\000\000\000\006\134\000\000\000\000\000\000\000\000\003.\000\000\000\000\0032\000\000\000\000\000\162\000\000\000\000\000\000\000\238\000\000\000\000\000\000\003:\000\000\000\000\000\000\000\000\006\138\007\226\000\165\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\003>\000\000\n\158\006\162\001.\003B\006\166\0016\001:\000\000\006\170\006\174\000\000\006\178\003F\000\000\n\166\000\000\000\000\000\226\001j\006\130\000\165\000\165\006\134\000\000\000\000\000\000\006\182\006\186\000\000\000\165\006\190\000\000\n\174\000\162\n\190\000\000\000\000\000\238\000\000\000\000\000\000\006\198\000\000\000\000\000\000\000\000\006\138\006\142\000\173\000\000\000\000\000\000\000\000\000\000\n\206\001\"\000\000\001&\000\000\000\000\000\000\000\000\006\202\000\000\n\158\006\162\001.\006\206\006\166\0016\001:\000\000\006\170\006\174\000\000\006\178\006\210\000\000\n\166\000\000\000\000\000\226\001j\006\130\000\173\000\173\006\134\000\000\000\165\000\000\006\182\006\186\000\000\n\198\006\190\n\182\n\174\000\162\n\190\000\000\000\000\000\238\000\000\000\000\000\000\006\198\000\000\000\165\000\000\000\000\006\138\006\194\n\150\000\000\000\000\000\000\000\000\000\000\n\206\001\"\000\000\001&\000\165\000\165\000\000\000\000\006\202\000\000\n\158\006\162\001.\006\206\006\166\0016\001:\000\000\006\170\006\174\000\000\006\178\006\210\000\000\n\166\000\000\000\000\000\226\001j\tz\000\189\n\238\t~\000\000\n\214\000\000\006\182\006\186\000\000\n\198\006\190\n\182\n\174\000\162\n\190\000\000\000\000\000\238\000\000\000\000\000\000\006\198\000\000\000\173\000\000\000\000\t\130\t\142\n\150\000\000\000\000\000\000\000\000\000\000\n\206\001\"\000\000\001&\000\173\000\173\000\000\000\000\006\202\000\000\n\158\t\162\001.\006\206\t\166\0016\001:\000\000\t\170\t\174\000\000\t\178\006\210\000\000\n\166\000\000\000\000\000\226\001j\tz\000\177\000\177\t~\000\000\n\214\000\000\006\182\t\182\000\000\n\198\t\186\n\182\n\174\000\162\n\190\000\000\000\000\000\238\000\000\000\000\000\000\t\194\000\000\000\189\000\000\000\000\t\130\t\190\000\000\000\000\000\000\000\000\000\000\000\000\n\206\001\"\000\000\001&\n\246\n\222\000\000\000\000\t\198\000\000\000\000\t\162\001.\t\202\t\166\0016\001:\000\000\t\170\t\174\000\000\t\178\t\206\000\000\000\000\000\000\000\000\000\226\001j\tz\000\000\000\000\t~\000\000\n\214\000\000\006\182\t\182\000\000\000\000\t\186\n\182\000\000\000\162\000\000\000\000\000\000\000\238\000\000\000\000\000\000\t\194\000\000\000\177\000\000\000\000\t\130\n*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\177\n\222\000\000\000\000\t\198\000\000\000\000\t\162\001.\t\202\t\166\0016\001:\000\000\t\170\t\174\000\000\t\178\t\206\000\000\000\000\000\000\000\000\000\000\001j\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\182\000\000\000\000\t\186\000\000\000\000\000\162\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\194\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\t\198\000\000\000\000\000\000\000\000\t\202\000\000\000\000\000\000\000r\000\000\000\000\000\000\000\000\t\206\000\000\000\000\000\000\000\000\000v\001j\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\000\000\0002\tN\000F\000J\000\000\000N\006F\000R\000V\006J\000Z\000\134\000^\020r\000b\006N\000f\000j\000n\006R\020z\001\153\000\000\000\000\001\153\000\000\008B\000\000\000\000\000r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\153\000\000\000v\001\153\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\162\000\000\001\153\n\150\000\000\000\000\001\153\000\000\001\153\001\153\000\000\000\130\000\000\000\000\000\000\000\000\000\000\001\153\000\000\n\158\001\153\000\000\001\153\000\000\000\134\000\000\000\000\t>\000\000\000\000\000\000\000\000\000\000\n\166\000\000\000\000\007M\000\000\000\000\000\185\n\238\000\000\001\153\000\000\000\000\000\000\000\000\000\000\n\198\000\000\000\000\n\174\000\000\n\190\001\153\007M\000\000\000\000\000\000\000\000\000\000\000\000\000\162\000\000\007M\007M\003\161\000\000\000\000\000\000\007M\000\000\000\000\n\206\000\000\000\000\001\153\003\186\000\000\001\153\000\000\000\000\000\000\001\153\000\000\000\000\000\000\000\000\007M\000\000\000\000\000\000\000\000\000\000\000:\001\153\000\000\007M\007M\000\000\001\153\001\153\000\000\000\000\000\000\007M\003\194\n\214\007M\007M\001\153\001\153\001\153\000\000\n\182\000\000\000\000\000\000\007M\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\185\000\000\007M\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007M\000\000\000\000\000\000\000\000\000\185\n\222\000\000\000\000\0002\0006\000F\000J\007M\000N\000\000\000R\000V\000\000\000Z\017\n\000^\000\000\000b\000\000\000f\000j\000n\000\000\000\000\000\000\000\000\000\000\007M\000\000\000\000\007M\007M\000r\017\014\007M\000\000\000\000\000\000\000\000\007M\007M\000\000\019r\000\237\007M\000\000\000\237\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\026\000\000\000\000\000\237\000\130\000\000\000\000\000\000\017\234\000\000\000\000\000\000\000\000\000:\004\"\000\000\000\000\000\134\000\237\000\000\000\237\000\237\000\213\000\000\000\000\000\213\000\000\000\000\000\000\004B\000\000\000\000\004*\000\000\004:\000\000\000\000\000\000\000\213\000\000\000\000\000\213\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\"\000\000\004J\000\162\000\213\000\000\000\213\000\213\000\205\000\000\000\000\000\205\000\000\000\000\000\237\000\213\017\030\000\000\004*\000\000\004:\000\000\000\000\000\000\000\205\000\000\000\000\000\205\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004R\000\000\000\205\000\237\000\213\000\000\000\205\0042\000\205\000\205\000\209\000\000\000\000\000\209\000\000\000\000\000\213\000\205\000\000\000\237\004*\000\000\000\205\000\000\000\237\000\237\000\209\000\000\000\000\000\209\000\000\000\000\000\000\000\000\000\237\004Z\000\237\000\000\000\213\000\000\000\209\000\213\000\205\000\000\000\209\0042\000\209\000\209\000\225\000\000\000\000\000\225\000\000\000\000\000\205\000\209\000\000\000\213\004*\000\000\000\209\000\000\000\213\000\213\004\026\000\000\000\000\000\225\000\000\000\000\000\000\000\000\000\213\000\213\000\213\000\000\000\205\000\000\004\"\000\205\000\209\000\000\000\225\0042\000\225\000\225\000\217\000\000\000\000\000\217\000\000\000\000\000\209\000\225\000\000\000\205\004*\000\000\004:\000\000\000\205\000\205\004\026\000\000\000\000\000\217\000\000\000\000\000\000\000\000\000\205\000\205\000\205\000\000\000\209\000\000\004\"\000\209\004J\000\000\000\217\0042\000\217\000\217\000\221\000\000\000\000\000\221\000\000\000\000\000\225\000\217\000\000\000\209\004*\000\000\004:\000\000\000\209\000\209\004\026\000\000\000\000\000\221\000\000\000\000\000\000\000\000\000\209\000\209\000\209\000\000\000\225\000\000\004\"\000\225\000\217\000\000\000\221\0042\000\221\000\221\000\229\000\000\000\000\000\229\000\000\000\000\000\217\000\221\000\000\000\225\004*\000\000\004:\000\000\000\225\000\225\004\026\000\000\000\000\000\229\000\000\000\000\000\000\000\000\000\225\000\225\000\225\000\000\000\217\000\000\004\"\000\217\004J\000\000\000\229\0042\000\229\000\229\004\018\000\000\000\000\000\245\000\000\000\000\000\221\004B\000\000\000\217\004*\000\000\004:\000\000\000\217\000\217\004\026\000\000\000\000\000\245\000\000\000\000\000\000\000\000\000\217\000\217\000\217\000\000\000\221\000\000\004\"\000\221\004J\000\000\000\245\0042\000\245\004z\004\018\000\000\000\000\000\233\000\000\000\000\000\229\004B\000\000\000\221\004*\000\000\004:\000\000\000\221\000\221\004\026\000\000\000\000\000\233\000\000\000\000\000\000\000\000\000\221\000\221\000\221\000\000\004R\000\000\004\"\000\229\004J\000\000\000\233\0042\000\233\000\233\004\018\000\000\000\000\000\241\000\000\000\000\000\245\004B\000\000\000\229\004*\000\000\004:\000\000\000\229\000\229\004\026\000\000\000\000\000\241\000\000\000\000\000\000\000\000\000\229\000\229\000\229\000\000\004R\000\000\004\"\000\245\004J\000\000\000\241\0042\000\241\004z\000\000\000\000\000\000\000\000\000\000\000\000\000\233\004B\000\000\000\245\004*\000\000\004:\000\000\000\245\000\245\000\000\000\000\000\000\000\000\003\153\000\000\000\000\003\153\004\130\004Z\000\245\003\153\004R\003\153\000\000\000\233\004J\003\153\003\153\0042\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\241\000\000\000\000\000\233\000\000\000\000\000\000\000\000\000\233\000\233\000\000\000\000\000\000\000\000\000\000\002-\000\000\000\000\000\233\004Z\000\233\000\000\004R\000\000\000\000\000\241\000\000\000\000\000\000\0042\000\000\003\153\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\241\002-\000\000\000\000\000\000\000\241\000\241\000\000\000\000\002-\000\000\000\000\002-\002-\000\000\000\241\004Z\000\241\000\000\020v\000F\000J\002-\000N\006F\000R\000V\006J\000Z\000\000\000^\020r\000b\006N\000f\000\000\000n\006R\020z\000\000\002-\000\000\000\000\000\000\003\153\000\000\000\000\000r\000\000\000\000\000\000\000\000\000\000\002-\000\000\000\000\000\000\000v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002-\000\000\000\000\002-\002-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002-\002-\000\000\000\000\000\000\002-\000\134\0002\005\030\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000\000\0002\005\030\000F\000J\000\000\000N\000\000\000R\000V\000r\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000v\000\000\003\161\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000v\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000\000\000\000\005\"\005&\000\000\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000\000\000\000\005\"\005&\000\000\0002\000\142\000F\000J\011}\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000\000\011}\000\000\000\000\000\000\000\000\000\000\000\000\t\226\005*\000r\000\000\000\000\000\000\000\000\011}\000\000\000\000\000\000\000\000\000v\011}\011}\000\000\000\000\t\234\000\000\t\246\000\000\0052\011}\000\000\000\000\011}\000\000\011}\000\000\000\000\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\000\000\158\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\011}\000\000\000\000\000\000\000\000\000\000\0002\005\030\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\n\002\000^\000\000\000b\000\000\000f\000j\000n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011}\000r\000\000\000\162\000\000\n\006\000\000\011}\000\000\000\000\000\000\000v\000\000\000\000\000\000\n\014\000\000\000\000\000\000\011}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\000\000\011}\011}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002!\000\000\000\134\000\000\000\000\000\000\021\002\005&\0002\005\030\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000\000\000\000\021\002\005&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021\014"))
+ ((16, "\001\128\000X\000\000\000\000\001\015\000\000\000\000\000\000\001\128\000\000\002,%\"\000\000\000\127;\208\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\191\000y\000\000%\"#\"C\146\000C<2\000\000\000\000\000\000\000\000B\244\000\005C\146\001 C\146\000\000\000U\000\000C\146\000\000\000\133\000\000\000\000\000\0032\202\000\000\000\0004\156\000\0005\028\000\1822\2022\202\016j\016j5\028\000\0006L\000\0006\2042\202\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0005t2\202\000\000\000\0005t\000\0005t\000\0005t\000\000\000\000\000\000\018\208\000\133\000\000\016j\000\000*\2202\202\02302\202\000\000\000\000\000\000\000\000\000\000\000\000\025`2\202\000\000\026N2\202\026\1742\202\027\1562\202\000\0002\202\000\0002\202\027\2522\202\028\2342\202\029J2\202\03082\202\030\1522\202\000\1462\202\000\000\000\000\000\000\000\000\000\0002\202\031\1342\202\031\2302\202 \2122\202\000\000\000\0002\202\000\000\015\254%\164\000\000\000\000\000\140\000\000\000\000\000\000\023\252\000\000\000\000\000\000\000\000\000\000\014\024\000\127\000\000%\164\000\000\000\251\016j\000\0002\202\000\222\000\000\000\000\000\133\000\000\000\000\000\000\000\000\001\028\000\000\000\000\001@\000\000\00052\202\000\000\0005\000\000\000\000\016j\001B\000\000\002\"\000\000\000\000\000\000\000\000\000\000\000\000\000\0007$2\202\000\0007$\000\0007$7$\000\000\000\000'\164\000\133\000\000\016j\002N\000\0002\202\002T\000\000\000\000\000\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016j\002^6L\000\000\000\000;\1602\202\000\0002\202\000\000\000\000\002f\000\000\000=5\244\003N2\202\003V\000\000\000\0006L\000=\000\000\000\000\000\000\000\000\000\000<\2166L=,6L=<6L>26L\000\0006L\000\0006L>`6L>\1806L?\1506L?\1966L@\0242\202\003\0206L\000\0006L@\2506LA(6LA|\003$\000\000\003\160\000\000\000\132%\"\000\000\000\132\000\000\000\000\003\1802\202\000\000\004$\000\0006L\004\140\000\000\016j\003\214\000\000\000\000\003\232\000\000\000\000\000\003\000\000\004\198\000\000%>B:\004\196\004\198\000\133\004P\005$D0\000C\000\000\000\000\001\006D\136\000\000\000\000\000\000\005(\005\024\001\"\005>D0\001\222D0\000\000\000\000\001 \000\000\000\000\004\146\000\000\004\162\005`D0\004\186\000\000\000\000\001\006\000\000\004\202\005\156\000\000D\222C\232\000\000\000\133\005\182\000\000\014\024\000\133\005\186\000\000\000\000#\214C\146\004\234\000\000\005j\000\000\005\002\000\000\000\162%\"\000\000%\"\000\000\004\240\000\000\000\162\000\000\012\246\018\240\005\192D0\005\018\005\232\000\000%\"\000\158\000\000\005\236\000\000\000\000\000\000\000\000\000\000\000\000\005\2102\202\005$\017\"\005\2142\202\0050\005\218\001\006\005^\006z\000\0007\1648$\016j\005<\000\000\005D8$\000\000\000\000\000\000\000\000\000\000\000\000\000\0008\1642\202\000\0008\164\000\0008\1648\164\000\000\000\000\022B\000\133\000\000\016j\005`\000\0002\202\005r\000\000\000\000\000\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000&.2\202\000\0002\202\000\000\005z\000\000\0005\000\000\000\000\000\000\000\000\000\000+@8$,.8$,b8$-P8$\000\0008$\000\0008$-\1328$.r8$.\1668$/\1488$/\2002\202\005\1668$\000\0008$0\1828$0\2348$1\216\016j\005\130\000\000\000\0002\202\000\000\006T\000\000\001J\006.2\202\006\000\000\000\006<2\202\006\008\000\000\003>\000\000\006z\006z\001J\000\000\001J\000\000\012\246\006z\006z\000\000\000\000\000\000\020\172\000\000\000\000\000\000\000\000\006L2\202\005\162\017\"\017\240\000\133\006v\000\000\006X3\132\006|3\132\006\1302\202\005\180\017\"\017\"\000g\0026\000Y\000\000\000\000\000\000\0026\000\000\002j\000g\000\000\000\000\005\184\000\000\000\000\000\000\006\142\000\000\006\144\000\000\000\000\006\192\006v2\202\005\204\006\160\000\000\019\190\006\136\016j\005\218\017\"\000\000\000\000\006\004\000\000\0009\000\000\003\226\000\000\001J\000\000\000\000\006X\000\000.(\018\240\006\156D0\005\252\006\214\000\000\000\133\000\000\000\0272\202(J\000\0009$2\202\006\n\000\000\016j\006\n\000\000\006\016\000\000\000\000\000\000\000\000\000\000\000\000\000\0009\1642\202\000\0009\164\000\0009\1649\164\000\000\000\000D\174\000\133\000\000\016j\006\018\000\0002\202\006\016\000\000\000\000\000\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016j\006\024:$\000\000\000\0002\202\000w2\202\006\022\006J(J(\242'\014\006\1962\202\006\156\000\000\000\000\000\133\006^(J\000\000\006\\(J\000\000\000\000\020X:$\021F:$\025p:$!\188:$\000\000:$\000\000:$$~:$(&:$E\216:$E\238:$F8:$Ff:$F\196:$F\218\000\000\000\000\0064\000\000\006D)\154\000\000*B\006J*B1\252\006L*B\000\000\000\000\000\000\000\000\000\000\006t(J\000\000\000\000\006F\000\000\007\030\000\000\000\133\000\000\000\027\007$\000\000\000N\006\250\000\133\006^\007\024D0\006n\000@\000\0002\202\007B\000\000\001\022\001\026\003\178\007,D0\006~\007T\000\000\000\0052\202\007X\000\000\007`\000\000\014\024\000\133\002\1722\202\007|\000\000\007\128\000\000\011\170\0009\000\000\011\170\000\000\000\000\019\190\002\2442\202\007\144\000\000\007\148\000\000\000\000\001\154\007h\000\133\006\206\007\128D0\006\210\000\210\000\0002\202\007\166\000\000\0009\000\000\000\000\007\198\000\000\011\170\000\000\007\142\016j\006\228\007\182\000\000\001\022\000\000\007\158D0\006\242\007\196\000\000\00302\202\007\200\000\000\007\202\000\000\014\024\000\133\003@2\202\007\206\000\000\007\208\000\000\000\000\000\000\007\198\000\000\000\000\0009\000\000\006z\000\000\001\022\000\000\000\000\001\024\017\240\000\000\001\024\000\000\000\000\007\006\000\000\0005\000\003\017\"\000\000\003\226\0009\003\226\000\000\0009\000\000\006z\000\000\006z\000\000\000\000\000\000\007\004\000\000\000\000\007\014\000\000\001\162\005.\000\013\003\226\000\000\000\000\000\000\003\"\000\000\006z\000\000\001\162\000\000\000\000\001\022\003\214\012\246\000\000\014\242\000\000\t\018\012\246\000\000\000\000\t\018\000\000\000\000\007\012\000\000\000\000\007\018\000\000\001\248\006z\000\000\001\248\000\000\000\000\007\128\000\000\0009\000\000\006z\000\000\000\000\000\000\015\1283\226\000\000\007\232\000\000\015\128\007\236\000\000\007\244\000\000.(\000\133\002\028\000\0002\202\007\246\000\000\007\218\007\212\000\133\007H\008\002D0\007T\002d\000\0002\202\008&\000\000\001\022\002\176\000\0002\202\008,\000\000\014\024\000\133\002\196\000\0002\202\008.\000\000\002\158\015\128\000\000\019\190\003<\000\0002\202\0080\000\000\000\000\000\000\008\022\008\006\000\133\007j\008\028D0\007~\004$\000\0002\202\008V\000\000\002.\000\000\0088\016j\007\144\008b\000\000\002\188\000\000\004j\000\0002\202\008d\000\000\014\024\000\133\004\140\000\0002\202\008h\000\000\002\158\000\000\000\000\007\162\000\000\002.\003\174\008\016\000\000\000\000\000\000\008\020\000\000\002\016\002d\000\000\012\246\008f\000\000\000\0002\202\007\214\006z\000\000\007\174\000\000\001\006\000\000\000\000\003h\012\246\000\000\012\246\000\000\007\160\000\000\003h\000\0006L\003\2046L\000\0006L\000\000\007\164\000\000\003\204\000\000\017\"\004\028\017\"\000\000\017\"\000\000\007\168\000\000\004\028\000\0006L\003\204\007\174\000\000;\028\000\133\004 ;\028\000\000;\028\000\000\007\178\000\000\004 \000\0006L\003\204\007\186\000\000\000\000\021\248\000\000\000\000\000\000\000\000\000\000\025H!x\000\000\006\160\000\000\005\222\000\000\000\000\007\254\000\133\000\000\000\000\000\000\000\164\005\222\000\000\002\238\002\130\002\130\000\000\002\018\002\130\000\000\007\242\000\000\000\000\000\000\000\000\000\000\000\000\008p\000\000\"\160\000\000%\"\005\222\000\000\003^\005\222\000\000\008~\000\000\005\222\008\130\000\000\005\234\006\030\008\132\000\000\008\134\000\000\0076\007\216\005\222\008\018\005\222\008\140\000\000\008\142\000\000\008\146\000\000%\"\000\000\002\154%\"\000\000\008\028\011\188\000\000\001\002\005\222\000\000\004\166\005\222\000\000\004\208\003\136\000\133\000\000\t\004\000\133\000\000\008$\000\000\000\000\000\000\000\000\008\164\000\000\006\030\005\222\008\166\000\000\008\178\000\000\005\222\008\180\000\000\005\222\008\182\000\000\008\144\005\222\008\186\000\000\015\180\006\030\005\222\008D\005\222\008\190\000\000\008\192\000\000\000\000\004\168\005\222\000\000\004\220\001\130\001\130\000\000\000\000\000\000\003\158\001\130\000\000\008J\000\000\000\000\000\000\000\000\005\222\000\000\004\200\005\222\000\000\004\234\003\196\000\133\008L\000\000\000\000\000\000\000\000\008\204\000\000\008\206\000\000\005\222\008\208\000\000\007\216\005\222\008\210\000\000\008\216\000\000-\006\008\140\008\182\007j\005\222\008\226\000\000\000\000\008\228\000\000\008\186-\006\005\222\008\234\000\000\005\222\008\238\000\000\008\246\000\000\005\222\008\128\005\222\008\250\000\000\t\008\000\000\000\133\008\140\000\000\000\000\021\248\000\000\000\000\0028\th\000\000\000\000\003^\000\000\000\000\000\0002\202\000\135\t\166\008\208\tR6L\000\000\003\1926L\000\000\008\166\000\000\000\000\000\000\000\000\000\000\002\150\000\000\003n\000\000\000\000\000\000\003\226C2\005lC2C2\005l\000\000\000\000\000N\000N\000N\000N\000\000\000\000\000\000\000\000\000\000\000\000(J\008\166\000\000\000\000\000\000;\160\000N\014@\0009\000\000\000\000\0009\000\000\007\198\000\000\000\000\000\135\000\000\000\000\008\240\001h\t`E\146\000\000\004nE\250\000\000\000\000\tb\tR\000\133\000\000\000\133\000\000\004n\000\000\004\140E\146\000\000\000\000\008\182\tr\006z\008\204\000\000\001\154\0009\000\000\007\198\000\000\014\196\005,\000\000\000\000\tp\000\000\000\000\0028\000\000\004\172\000\000\000\000\000\0002\202\000\135\000\000\002\150\000\000\004\230\000\000\000\000\000\000\005.\000\000\n^\001\020\n^\000\000\006z\n^\000\000\001\020\000\000\006z\000\000\006z\000\000\006z\000\000\000\000\000\000\000\000\000\000\000\135\000\000\006z\000\000\001\020\000\000\006z\000\000\017H\000\000\000\000\t\018\t\008\000\133\003\144\t\152\004`\000\000\004`\t\194\000\000\t\196\000\000\t\200\000\000\000\000\001*\004`\012\244\004`\000\000\000\000\000\152\008\220\000\000\t\206\000\000\000\000\t\018\007\184\002\202\t\234\n\248\t\234\000\000\000\000\007\250\000\133\000\000\004\024\tD\000\000\000\000\000\000\004\192\000\000\008\246\000\000\000\000\000\000\007\184\002\202\007\250\004\024\004\192\008\252\000\000\000\133\000\000\t\242\t\238\t<\000\133\t\144\000\000"), (16, "\n\149\n\149\n\149\n\149\n\149\n\149\n\149\n\149\n\149\n\149\n\149\000:\n\149\n\149\n\149\n\149\n\149\n\149\n\149\n\149\n\149\tJ\000\210\tJ\002\174\n\149\000\023\000\027\003i\005\197\008\002\n\149\0055\n\149\n\149\n\149\n1\000\210\n\149\0086\000z\000\146\n\149\n\149\000\210\n\149\006F\n1\005=\006J\000\162\002\242\008\002\020\178\n\149\006N\000~\n\149\n\149\006R\020\182\0086\020>\n\149\n\149\000\162\n\149\000\222\n\149\000\174\0119\003\233\000\162\n\149\nf\n\149\n\149\n\149\n\149\n\149\000\n\011\186\008\186\n\149\n\149\n\149\n\149\n\149\n\149\008\194\n\149\n\149\n\149\n\149\005\229\005\229\011f\n\149\n\149\005\229\000\014\0119\002\253\003\218\011\158\tV\003%\n\149\n\149\n\149\n\149\n\149\n\149\n\149\000\194\n\149\002U\n\149\t\146\n\149\002U\003%\n\149\n\149\005\197\005\242\005\157\tV\n\149\011\238\005=\013f\n\149\0119\0119\n\149\011\134\022\182\0119\n\149\n\149\n\149\n\149\004\158\n\149\n\149\003\233\011\134\005=\n\149\n\149\n\149\005=\n\149\012z\n\149\n\149\0066\n\149\003\181\n\149\n\149\000\250\011\190\n\149\n\149\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\ny\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\005\205\tJ\012\190\005\250\004q\005\205\008\006\008\022\008&\000\162\008\002\005\205\003%\005\205\005\205\005\205\003%\003%\005\205\0086\004\005\002\026\005\205\004q\022\182\005\205\006F\000\182\003%\006J\004\158\013B\005\149\020\178\005\205\006N\000\006\002r\001.\006R\020\182\011\206\001:\005\205\005\205\017J\000\210\000\210\005\205\005\205\012~\0136\003%\005\205\022\190\005\205\005\205\005\205\005\205\005\205\007\217\005m\018.\005\205\005\205\005\205\005\205\005\205\005\205\000\162\005\205\005\205\005\205\005\205\000\162\000\162\018\246\005\205\005\205\001.\002\190\008\t\0016\001:\012^\tV\004q\006z\005\205\005\205\005\205\005\205\005\205\005\205\005.\005\205\016\018\005\205\005U\005\205\013\182\005E\005\205\005\205\004q\005\149\005\189\007\013\005\205\002\222\000\162\007\013\005J\008\t\008\t\005\205\022\198\018\250\008\t\005\205\005\205\005\205\005\205\000\162\005\205\005\205\002\234\022\190\003\014\005\205\005\205\005\205\005\237\014\158\005\237\005\205\005\205\005\237\005\205\003\181\005\205\005\205\015r\0146\005\205\005\205\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\008*\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005e\005e\014\206\002\242\005\237\005\237\020\026\005\237\005\165\n!\005\237\0172\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\005\237\000.\006\018\016Z\016\130\016\170\016\186\016\230\005\237\022\238\005V\005\237\017Z\n1\002y\014\230\005\237\005\237\005\237\005\237\005\237\015\142\005\237\014\162\005\213\015\002\005\173\005\237\020\026\005\237\005\237\005\237\005\237\005\237\015\022\015\250\017f\005\237\005\237\005\237\005\237\005\237\005\237\nI\005\237\005\237\005\237\005\237\003\022\n1\014b\005\237\005\237\005\157\008\190\014f\005\237\001.\005]\014\210\011\206\001:\005\237\005\237\005\237\005\237\005\237\005\237\017V\005\237\003j\005\237\tJ\005\237\008*\003v\005\237\005\237\003\170\n1\008\218\008\002\005\237\003\210\003\001\015&\005\237\n1\000\162\005\237\0086\015\230\006\021\005\237\005\237\012\014\005\237\014\234\005\237\005\237\003\233\005\213\016:\005\237\018\022\005\213\005\213\015\006\008.\005\181\005\237\n)\005\237\011\134\005\237\005\237\003\226\005\213\005\237\005\237\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\012B\000^\020\146\000b\006N\000f\000j\000n\006R\020\154\005\213\015\142\018J\004m\006V\006\021\003\234\nY\011\134\004j\000r\016b\000\226\006f\006\130\tV\007!\006\134\014b\004\001\012\218\000v\004m\014f\007\242\016B\015*\014j\012\250\004\158\008\002\007!\019B\000\238\003\233\004\142\008\002\001.\011\134\0086\011\206\001:\008J\006\142\020\214\0086\011\134\008N\013r\000\162\023\018\016\138\001\"\016\198\001&\003\197\000\134\tR\008V\015\230\015^\017\170\006\162\001.\008Z\006\166\008^\001:\000\162\006\170\006\174\008b\006\178\020+\020/\016j\022\134\008f\0203\000\162\007!\020\131\020\135\005\133\022\142\004m\020\139\006\182\006\186\008j\008n\006\190\008r\019\n\000\162\015\150\008\134\004\150\003\161\003!\nA\008\146\006\198\004m\005\149\tV\022\146\005\245\004\182\004\194\020V\tV\015\178\022\150\008\178\016\146\n9\016\206\008\182\008\242\003\197\t^\004\206\006\202\008\246\004\218\007!\023\026\006\206\003\197\003\197\003\129\023\030\005}\003\197\008\254\004\230\006\210\007!\005\245\005\245\004\250\015b\001j\005\245\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\005\n\000^\020\146\000b\006N\000f\000j\000n\006R\020\154\005\014\003\129\018F\022\158\006V\ni\na\005\141\018\242\005u\000r\015\154\000\226\006f\006\130\019>\0055\006\134\021\167\0055\005\022\000v\nq\0055\007\242\0055\006\005\021\171\015\182\0055\0055\021:\005\253\000\238\022\166\005M\008\002\021\174\005\026\006\013\005B\005F\008J\006\142\020\214\0086\021j\008N\013\186\023&\002m\005N\001\"\005r\001&\003\213\000\134\tR\008V\018:\018\230\005z\006\162\001.\008Z\006\166\008^\001:\005~\006\170\006\174\008b\006\178\005\134\021\199\021\203\0192\008f\017*\021\207\006\005\005\154\005\158\002b\017\202\004\217\005\253\006\182\006\186\008j\008n\006\190\008r\006\013\000\162\005\182\008\134\005\198\003\161\017.\005\218\008\146\006\198\021\235\021\239\017.\005\226\006\029\021\243\0172\017*\tV\005\234\006\007\008\178\0172\006\030\006&\008\182\008\242\006*\t^\006>\006\202\008\246\006Z\006b\006j\006\206\0055\003\213\017.\006r\006v\019\226\008\254\006~\006\210\006\150\006\029\006\029\0172\006\158\001j\006\029\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\006\246\000^\020\146\000b\006N\000f\000j\000n\006R\020\154\018\194\007\002\007J\t\205\006V\018~\007\194\007\234\007\254\007\221\000r\008\n\000\226\006f\006\130\008\018\000\162\006\134\008\026\008\"\008v\000v\000\162\008~\007\242\008\142\008\150\t\205\008\158\017>\007\221\008\166\008\174\000\238\008\234\017>\008\002\008\250\t\002\t\014\007\221\t\018\0082\006\142\t\026\0086\t\030\008N\000\162\017\"\t*\t2\001\"\tB\001&\003\241\000\134\008R\008V\tf\tv\017>\006\162\001.\008Z\006\166\008^\001:\t~\006\170\006\174\008b\006\178\t\130\t\170\t\182\011A\008f\t\190\n\018\n\030\t\205\nR\nn\017\226\nr\n\130\006\182\006\186\008j\008n\006\190\008r\n\138\000\162\n\154\008\134\n\166\003\161\011*\0112\008\146\006\198\011B\011N\017.\011j\008\017\011z\011\130\004a\tV\011\150\007\221\008\178\0172\011\162\011\170\008\182\008\242\003\241\t^\011\174\006\202\008\246\011\182\007\221\011\198\006\206\003\241\003\241\004a\011\218\011\226\003\241\008\254\011\230\006\210\011\246\008\017\008\017\004a\011\254\001j\008\017\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\012\022\000^\012\030\000b\006N\000f\000j\000n\006R\017*\012J\003!\012R\t\193\006V\012b\004a\012j\012n\012v\000r\012\134\000\226\006f\006\130\012\170\003!\006\134\012\178\012\182\017.\000v\000\162\012\198\007\242\012\206\012\210\t\193\012\226\012\234\0172\013\002\013\n\000\238\013Z\017>\008\002\013\162\013\174\014\"\014.\014N\0082\006\142\014z\0086\014\134\008N\004a\005\221\014\142\014\170\001\"\014\178\001&\017\230\000\134\008R\008V\014\182\019z\004a\006\162\001.\008Z\006\166\008^\001:\014\190\006\170\006\174\008b\006\178\014\194\014\202\014\218\011A\008f\014\242\015\014\0152\t\193\t\205\015B\015F\015N\015R\006\182\006\186\008j\008n\006\190\008r\003!\000\162\015Z\008\134\003!\003!\015j\015z\008\146\006\198\000\162\015\130\015\134\015\162\011A\015\190\003!\022\134\tV\015\210\015\226\008\178\015\242\017>\016\n\008\182\008\242\016\026\t^\016&\006\202\008\246\016O\005\221\016w\006\206\016\159\005\221\005\221\016\183\003!\016\219\008\254\t\205\006\210\016\243\011A\011A\0176\023\006\001j\011A\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\017r\000^\017\143\000b\006N\000f\000j\000n\006R\017\183\005\221\017\195\017\211\017\219\006V\017\238\017\247\017\255\003\141\018\007\000r\018\"\000\226\006f\006\130\018b\nQ\006\134\018w\018\135\022z\000v\007)\003\141\007\242\018\143\018\155\018\167\018\174\018\183\018\202\018\211\018\219\000\238\019\022\019J\008\002\007)\019_\019g\019s\019\131\0082\006\142\019\139\0086\019\150\008N\019\154\019\167\019\179\019\186\001\"\019\199\001&\019\211\000\134\008R\008V\019\219\019\230\019\239\006\162\001.\008Z\006\166\008^\001:\019\247\006\170\006\174\008b\006\178\020\003\020\030\020B\020F\008f\020J\020b\020\222\021&\021.\021J\021N\021z\007)\006\182\006\186\008j\008n\006\190\008r\nQ\000\162\021~\008\134\nQ\nQ\021\134\003\141\008\146\006\198\022\214\003\141\003\141\021\179\022~\022\138\022\154\022\162\tV\022\170\022\211\008\178\022\218\003\141\003\141\008\182\008\242\018V\t^\022\242\006\202\008\246\023\022\023/\nQ\006\206\023S\023b\023f\007)\nQ\023j\008\254\023s\006\210\000\000\000\000\003\141\000\000\000\000\001j\007)\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000\000\000^\020\146\000b\006N\000f\000j\000n\006R\020\154\000\000\000\000\000\000\000\000\006V\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\226\006f\006\130\000\000\000\000\006\134\000\000\000\000\000\000\000v\000\000\000\000\007\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008J\006\142\000\000\000\000\000\000\008N\022\002\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\134\tR\008V\000\000\000\000\000\000\006\162\001.\008Z\006\166\008^\001:\000\000\006\170\006\174\008b\006\178\000\000\000\000\000\000\000\000\008f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008j\008n\006\190\008r\000\000\000\162\000\000\008\134\000\000\003\161\000\000\n\025\008\146\006\198\000\000\000\000\000\000\000\000\007\245\000\000\000\000\000\000\000\000\000\000\000\000\008\178\000\000\000\000\000\000\008\182\008\242\000\000\t^\000\000\006\202\008\246\000\000\000\000\000\000\006\206\000\000\000\000\000\000\000\000\000\000\000\000\008\254\000\000\006\210\000\000\007\245\007\245\000\000\000\000\001j\007\245\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\0055\000\000\000\000\000\000\000\000\006V\000\000\000\000\000\000\000\000\000\000\000r\n\025\000\226\006f\006\130\n\025\n\025\006\134\000\000\000\000\0055\000v\000\000\000\000\007\242\000\000\000\000\n\025\000\000\000\000\0055\000\000\000\000\000\238\000\000\000\000\000\000\000\000\022\246\000\000\000\000\000\000\008J\006\142\000\000\000\000\000\000\008N\012&\000\000\000\000\n\025\001\"\000\000\001&\0055\000\134\tR\008V\000\000\000\000\002b\006\162\001.\008Z\006\166\008^\001:\000\000\006\170\006\174\008b\006\178\000\000\000\000\000\000\011\029\008f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008j\008n\006\190\008r\000\000\000\162\000\000\008\134\000\000\000\000\000\000\000\000\008\146\006\198\0055\000\000\000\000\000\000\011\029\000\000\000\000\000\000\000\000\000\000\000\000\008\178\000\000\0055\000\000\008\182\008\242\000\000\t^\000\000\006\202\008\246\000\000\000\000\000\000\006\206\000\000\000\000\000\000\000\000\000\000\000\000\008\254\000\000\006\210\000\000\011\029\011\029\000\000\000\000\001j\011\029\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\000\000\000\000\000\000\000\000\000\000\006V\000\000\000\000\003\029\000\000\000\000\000r\000\000\000\226\006f\006\130\000\000\000\000\006\134\000\000\000\000\000\000\000v\003\029\000\000\007\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\003\029\000\000\000\000\000\000\008J\006\142\000\000\000\000\000\000\008N\013\238\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\134\tR\008V\000\000\000\000\000\000\006\162\001.\008Z\006\166\008^\001:\000\000\006\170\006\174\008b\006\178\000\000\000\000\000\000\000\000\008f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008j\008n\006\190\008r\000\000\000\162\000\000\008\134\000\000\000\000\003\029\000\000\008\146\006\198\003\029\003\029\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\178\003\029\000\000\000\000\008\182\008\242\000\000\t^\000\000\006\202\008\246\002\154\000F\000J\006\206\000N\003\029\000R\000V\000\000\000Z\008\254\000^\006\210\000b\003\029\000f\022\190\000n\001j\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000r\000^\000\000\000b\006N\000f\000j\000n\006R\000\000\000\000\000v\000\000\000\000\006V\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\226\006f\006\130\000\000\000\000\006\134\000\000\000\000\000\000\000v\000\000\000\000\007\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\134\000\000\000\000\000\000\000\000\000\000\008J\006\142\000\000\000\000\000\000\008N\020\246\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\134\tR\008V\000\000\000\000\000\000\006\162\001.\008Z\006\166\008^\001:\000\000\006\170\006\174\008b\006\178\000\000\000\162\000\000\000\000\008f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008j\008n\006\190\008r\012\190\000\162\000\000\008\134\000\000\000\000\000\000\000\000\008\146\006\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007!\000\000\000\000\008\178\000\000\tJ\000\000\008\182\008\242\000\000\t^\000\000\006\202\008\246\008\002\007!\000\000\006\206\001.\000\000\000\000\011\206\001:\0086\008\254\000\000\006\210\000\000\0002\006\022\000F\000J\001j\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\000\000\000\162\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\226\006\229\006\130\007!\018\190\006\134\000\000\000\000\000\000\000v\000\000\000\000\014n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\017.\000\000\000\000\tV\000\000\014~\006\142\000\000\006\229\006\229\0172\000\000\000\000\006\229\000\000\001\"\0055\001&\000\000\000\134\000\000\000\000\000\000\000\000\007!\006\162\001.\000\000\006\166\0016\001:\000\000\006\170\006\174\008b\006\178\007!\0055\000\000\000\000\000\000\000:\000\000\000\000\000\000\000\000\000\000\0055\0055\000\000\006\182\006\186\000\000\000\000\006\190\000\000\000\000\000\162\000\000\0002\0006\000F\000J\000\000\000N\006\198\000R\000V\000\000\000Z\000\000\000^\0055\000b\000\000\000f\000j\000n\002b\000\000\000\000\0055\0055\000\162\t^\000\000\006\202\014\130\000\000\000\000\000r\006\206\000\226\000\000\000\230\000\000\017>\000\234\014\138\000\000\006\210\000v\000\000\000\000\000\000\000\000\001j\000\000\000\000\000\000\000\000\000\000\0055\000\238\000\000\000\000\000\242\000\000\000\000\000\000\0055\000\000\001\006\001\002\000\000\001\n\000\000\000\000\000\000\000\000\000\000\000\000\001\"\0055\001&\000\000\000\134\000\000\000\000\000\000\000\000\000\000\001*\001.\000\000\0012\0016\001:\001\142\001>\001B\000\000\001F\0055\000\000\000\000\0055\0055\000\000\000\000\0055\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001J\000\000\0055\001N\000\000\000\000\000\162\000\000\006V\000\000\000\000\000\000\000\000\000\000\001V\000\000\000\226\006f\006\130\000\000\000\000\006\134\000\000\001Z\000\000\000\000\000\000\000\000\007\242\000\000\000\000\000\000\000\000\000\000\000\000\001^\000\000\000\238\000\000\000\000\001b\000\000\000\000\003e\000\000\000\000\008\130\006\142\000\000\001f\012\190\008N\000\000\000\000\000\000\001j\001\"\000\000\001&\000\000\000\000\000\000\008V\000\000\000\000\000\000\006\162\001.\008Z\006\166\008^\001:\000\000\006\170\006\174\000\000\006\178\000\000\000\000\000\000\000\000\008f\000\000\000\000\000\000\000\000\001.\000\000\000\000\011\206\001:\006\182\006\186\008j\008n\006\190\008r\000\000\000\162\000\000\008\134\000\000\000\000\000\000\000\000\008\146\006\198\000\000\000\000\000\000\000\000\006V\000\000\000\000\000\000\000\000\000\000\000\162\008\178\000\226\006f\006\130\008\182\008\242\006\134\000\000\000\000\006\202\008\246\000\000\008A\007\242\006\206\000\000\000\000\000\000\000\000\000\000\000\000\008\254\000\238\006\210\000\000\000\000\000\000\000\000\000\000\001j\000\000\006\138\006\142\000\000\000\000\000\000\008N\000\000\000\000\000\000\000\000\001\"\000\000\001&\008A\008A\000\000\008V\000\000\008A\000\000\006\162\001.\008Z\006\166\008^\001:\000\000\006\170\006\174\000\000\006\178\000\000\000\000\000\000\000\000\008f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\006\186\008j\008n\006\190\008r\000\000\000\162\000\000\008\134\000\000\000\000\000\000\000\000\008\146\006\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011m\0055\008\178\011m\0055\000\000\008\182\008\242\0055\000\000\0055\006\202\008\246\000\000\0055\0055\006\206\000\000\011m\000\000\000\000\000\000\011m\008\254\000\000\006\210\001\130\011m\000\000\000\000\000\000\001j\000\000\011m\000\000\000\000\011m\011m\000\000\011m\011m\000\000\000\000\001\138\000\000\011m\002\182\000\000\000\000\011m\000\000\000\000\011m\000\000\011m\011m\000\000\000\000\000\000\0055\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\146\000\000\000\000\000\000\000\000\000\000\011m\000\000\011m\000\000\000\000\001.\000\000\000\000\0016\001:\000\000\000\000\011m\000\000\000\000\000\000\000\000\002\194\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011m\011m\011m\000\162\011m\011m\002\198\0055\011m\000\000\000\000\000\000\004\001\000\000\000\000\004\001\002\206\000\000\000\000\000\000\011m\000\000\000\000\011m\011m\011m\011m\000\000\000\000\000\000\004\001\011m\011m\011m\004\001\011m\011m\011m\004\001\004\001\000\000\000\000\000\000\000\000\000\000\004\001\000\000\000\000\004\001\004\001\000\000\004\001\004\001\000\000\000\000\004\001\000\000\004\001\004\001\000\000\000\000\004\001\000\000\000\000\004\001\000\000\004\001\004\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\000\000\004\001\n\182\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\000\000\000\000\000\000\000\000\004\001\000\000\000\000\000\162\n\190\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\004\001\004\001\n\198\004\001\004m\004\001\000\000\004\001\011\006\011\014\000\000\004\005\000\000\000\000\004\005\004\001\000\000\000\000\n\230\004\001\000\000\n\206\004\001\n\222\004\001\000\000\000\000\000\000\000\000\004\005\004\001\004\001\004\001\004\005\004\001\004\001\004\001\004\005\004\005\000\000\000\000\000\000\000\000\n\238\004\005\000\000\000\000\004\005\004\005\000\000\004\005\004\005\000\000\000\000\004\005\000\000\004\005\004\005\000\000\000\000\004\005\000\000\000\000\004\005\000\000\004\005\004\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\246\000\000\000\000\000\000\000\000\000\000\000\000\n\214\004\005\000\000\004\005\000\181\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\169\004\005\000\000\000\000\000\000\000\000\004\005\000\000\000\000\000\000\n\190\000\000\000\000\000\000\000\000\011\022\n\254\000\000\000\000\000\000\000\000\000\000\004\005\004\005\004\005\n\198\004\005\004q\004\005\000\000\004\005\000\181\000\181\000\000\000\000\000\000\000\000\000\000\004\005\000\000\000\000\n\230\004\005\000\000\n\206\004\005\n\222\004\005\000\000\000\000\000\000\000\000\000\000\004\005\004\005\004\005\000\000\004\005\004\005\004\005\001=\001=\001=\001=\000\000\001=\n\238\001=\001=\000\000\001=\000\000\001=\000\000\001=\000\000\001=\001=\001=\000\000\000\000\000\000\000\000\016\254\000\000\000\000\000\000\000\000\000\000\000\000\001=\001=\001=\000\000\000\000\000\000\000\000\001=\000\000\000\000\n\246\000\000\001=\000\000\000\000\000\000\001=\n\214\000\000\000\000\001=\000\000\000\000\017\002\000\000\000\000\001=\000\000\011\193\000\181\000\000\011\193\000\000\001=\000\000\000\000\000\000\000\000\001=\000\000\000\000\000\000\000\000\000\000\000\181\n\254\011\193\001=\000\000\000\000\011\193\000\000\000\000\000\000\006\230\011\193\000\000\000\000\000\000\000\000\000\000\011\193\000\000\000\000\011\193\011\193\001=\011\193\011\193\001=\000\000\006\238\000\000\011\193\006\250\000\000\000\000\011\193\000\000\000\000\011\193\000\000\011\193\011\193\001=\000\000\001=\000\000\001=\000\000\001=\000\000\000\000\000\000\000\000\001=\000\000\000\000\001=\000\000\000\000\000\000\011\193\000\000\011\193\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001=\011\193\000\000\001=\001=\000\000\007\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\193\011\193\011\193\000\000\011\193\000\000\007\n\000\000\011\193\000\000\000\000\000\000\001\137\000\000\000\000\001\137\007\018\000\000\000\000\000\000\000\000\000\000\000\000\011\193\000\000\011\193\000\000\000\000\000\000\000\000\001\137\011\193\011\193\011\193\001\137\011\193\011\193\011\193\000\000\001\137\000\000\000\000\000\000\000\000\000\000\001\137\000\000\000\000\001\137\001\137\000\000\001\137\001\137\000\000\000\000\000\000\000\000\001\137\000\000\000\000\000\000\001\137\000\000\000\000\001\137\000\000\001\137\001\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\137\000\000\001\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\137\004%\000\000\002\130\004%\002\134\004%\002\138\004%\000\000\004%\000\000\000\000\002\142\004%\004%\000\000\000\000\000\000\000\000\000\000\001\137\001\137\001\158\000\000\001\137\001\137\004%\000\000\001\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\004%\000\000\000\000\001\137\000\000\004%\001\137\001\137\001\137\001\137\000\000\000\000\000\000\000\000\002J\001\137\001\137\000\000\001\137\001\137\001\137\004%\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\004%\004%\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\004%\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\004%\004%\000\000\000\000\004%\000\000\000\000\000\000\000\000\004%\004%\000\000\000\000\000\000\004%\t\189\t\189\t\189\t\189\000\000\t\189\000\000\t\189\t\189\000\000\t\189\000\000\t\189\000\000\t\189\000\000\t\189\t\189\t\189\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\189\t\189\t\189\001\190\000\000\000\000\002\018\t\189\000\000\000\000\000\000\000\157\t\189\000\000\000\000\000\000\017\022\000\000\000\000\000\000\017\030\001\202\000\000\000\000\000\000\002\001\t\189\000\000\000\000\000\157\002\001\000\000\000\000\t\189\000\000\000\000\001\210\000\000\t\189\002\001\002\001\000\000\0022\002:\n\198\000\000\000\000\t\189\002\001\000\000\000\157\000\157\001\242\000\000\000\000\001\218\000\000\001\234\002\001\000\000\000\157\000\000\000\000\n\206\000\000\n\222\t\189\000\000\000\000\t\189\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\250\000\000\002\001\000\000\000\000\000\000\000\000\t\189\000\157\t\189\000\000\t\189\002\001\t\189\000\000\000\000\000\000\000\000\t\189\000\000\000\000\t\189\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\001\002\002\000\000\t\189\002\001\002\001\017\146\t\189\001\226\000\157\000\000\000\000\000}\000\000\000\000\000}\n\214\000\000\000\000\000\000\002\001\000\000\000\000\002\001\002\001\002\001\002\001\000\000\000\157\000\000\001\202\000\000\002\001\002\001\000}\002B\002\n\002\001\000\000\000}\000\000\000\000\000\000\000\157\000\157\001\210\000\000\000\000\000}\000}\000\000\000}\000}\000\000\000\000\000\000\000\000\000}\000\000\000\000\000e\001\242\000\000\000e\001\218\000\000\001\234\000}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000e\000\000\000\000\000\000\000e\000\000\000\000\000\000\001\250\000e\000}\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000e\000e\000}\000e\000e\000\000\000\000\000\000\000\000\000e\000\000\000\000\000\000\000e\000\000\000\000\001\218\000\000\001\234\000e\000\000\000\000\000\000\000}\002\002\000\000\000\000\000}\000}\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\000e\000\000\000e\000\000\000\000\000}\000\000\000\000\000}\000}\000}\000}\000e\000\000\000\000\000\000\000\000\000}\000}\000\000\000}\002\n\000}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000e\000e\000\000\000\000\000e\000e\000\000\000\000\001\226\000\000\000\000\000\000\000]\000\000\000\000\000]\000\000\000\000\000\000\000\000\000e\000\000\000\000\000e\000e\000e\000e\000\000\000\000\000\000\000]\000\000\000e\000e\000]\000e\000e\000e\000\000\000]\000\000\000\000\000\000\000\000\000\000\000]\000\000\000\000\000]\000]\000\000\000]\000]\000\000\000\000\000\000\000\000\000]\000\000\000\000\000a\000]\000\000\000a\001\218\000\000\000]\000]\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000a\000\000\000\000\000\000\000a\000\000\000\000\000\000\000]\000a\000]\000\000\000\000\000\000\000\000\000a\000\000\000\000\000a\000a\000]\000a\000a\000\000\000\000\000\000\000\000\000a\000\000\000\000\000\000\000a\000\000\000\000\001\218\000\000\000a\000a\000\000\000\000\000\000\000]\000]\000\000\000\000\000]\000]\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\000a\000\000\000a\000\000\000\000\000]\000\000\000\000\000]\000]\000]\000]\000a\000\000\000\000\000\000\000\000\000]\000]\000\000\000]\000]\000]\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000a\000a\000\000\000\000\000a\000a\000\000\000\000\001\226\000\000\000\000\000\000\000q\000\000\000\000\000q\000\000\000\000\000\000\000\000\000a\000\000\000\000\000a\000a\000a\000a\000\000\000\000\000\000\001\202\000\000\000a\000a\000q\000a\000a\000a\000\000\000q\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000q\000q\000\000\000q\000q\000\000\000\000\000\000\000\000\000q\000\000\000\000\000i\000q\000\000\000i\001\218\000\000\001\234\000q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\202\000\000\000\000\000\000\000i\000\000\000\000\000\000\001\250\000i\000q\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000i\000i\000q\000i\000i\000\000\000\000\000\000\000\000\000i\000\000\000\000\000\000\000i\000\000\000\000\001\218\000\000\001\234\000i\000\000\000\000\000\000\000q\000q\000\000\000\000\000q\000q\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\000i\000\000\000i\000\000\000\000\000q\000\000\000\000\000q\000q\000q\000q\000i\000\000\000\000\000\000\000\000\000q\000q\000\000\000q\000q\000q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000i\000i\000\000\000\000\000i\000i\000\000\000\000\001\226\000\000\000\000\000\000\000m\000\000\000\000\000m\000\000\000\000\000\000\000\000\000i\000\000\000\000\000i\000i\000i\000i\000\000\000\000\000\000\001\202\000\000\000i\000i\000m\000i\000i\000i\000\000\000m\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000m\000m\000\000\000m\000m\000\000\000\000\000\000\000\000\000m\000\000\000\000\000u\000m\000\000\000u\001\218\000\000\001\234\000m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\202\000\000\000\000\000\000\000u\000\000\000\000\000\000\001\250\000u\000m\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000u\000u\000m\000u\000u\000\000\000\000\000\000\000\000\000u\000\000\000\000\000\000\001\242\000\000\000\000\001\218\000\000\001\234\000u\000\000\000\000\000\000\000m\000m\000\000\000\000\000m\000m\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\001\250\000\000\000u\000\000\000\000\000m\000\000\000\000\000m\000m\000m\000m\000u\000\000\000\000\000\000\000\000\000m\000m\000\000\000m\000m\000m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000u\002\002\000\000\000\000\000u\000u\000\000\000\000\001\226\000\000\000\000\000\000\001\190\000\000\000\000\000\133\000\000\000\000\000\000\000\000\000u\000\000\000\000\000u\000u\000u\000u\000\000\000\000\000\000\001\202\000\000\000u\000u\000\133\000u\000u\000u\000\000\000\133\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\133\000\133\000\000\000\133\002:\000\000\000\000\000\000\000\000\000\133\000\000\000\000\001\190\001\242\000\000\000y\001\218\000\000\001\234\000\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\202\000\000\000\000\000\000\000y\000\000\000\000\000\000\001\250\000y\000\133\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000y\000y\000\133\000y\000y\000\000\000\000\000\000\000\000\000y\000\000\000\000\000\000\001\242\000\000\000\000\001\218\000\000\001\234\000y\000\000\000\000\000\000\000\133\002\002\000\000\000\000\000\133\000\133\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\000\000\001\250\000\000\000y\000\000\000\000\000\133\000\000\000\000\000\133\000\133\000\133\000\133\000y\000\000\000\000\000\000\000\000\000\133\000\133\000\000\002B\002\n\000\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000y\002\002\000\000\000\000\000y\000y\000\000\000\000\001\226\000\000\000\000\000\000\001\190\000\000\000\000\000\129\000\000\000\000\000\000\000\000\000y\000\000\000\000\000y\000y\000y\000y\000\000\000\000\000\000\001\202\000\000\000y\000y\000\129\000y\002\n\000y\000\000\000\129\000\000\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\129\000\129\000\000\000\129\002:\000\000\000\000\000\000\000\000\000\129\000\000\000\000\000\000\001\242\000\000\000\000\001\218\000\000\001\234\000\129\000\000\000\000\000\000\000\000\000\000\t\173\t\173\t\173\t\173\000\000\t\173\000\000\t\173\t\173\000\000\t\173\000\000\t\173\001\250\t\173\000\129\t\173\t\173\t\173\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000\000\000\000\000\000\000\000\t\173\t\173\t\173\000\000\000\000\000\000\000\000\t\173\000\000\000\000\000\000\000\000\t\173\000\000\000\000\000\000\000\129\002\002\000\000\000\000\000\129\000\129\000\000\000\000\001\226\000\149\t\173\000\000\000\000\000\000\000\000\000\000\000\000\t\173\000\000\000\000\000\129\000\000\t\173\000\129\000\129\000\129\000\129\000\149\000\000\000\000\000\000\t\173\000\129\000\129\000\000\000\129\002\n\000\129\000\000\000\000\000\000\000\000\000\149\000\000\000\000\000\000\000\000\000\000\000\149\000\149\t\173\000\000\000\000\t\173\000\000\000\000\000\000\000\000\000\149\000\000\000\000\n\206\000\000\000\149\000\000\000\000\000\000\000\000\t\173\000\000\t\173\000\000\t\173\000\000\t\173\000\000\000\000\000\000\000\000\t\173\000\000\000\000\t\173\000\149\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\173\000\000\000\000\017\026\t\173\t\177\t\177\t\177\t\177\000\000\t\177\000\000\t\177\t\177\000\000\t\177\000\000\t\177\000\000\t\177\000\149\t\177\t\177\t\177\000\000\000\000\000\000\n\214\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\177\t\177\t\177\000\000\000\149\000\000\000\000\t\177\000\000\000\000\000\000\000\000\t\177\000\000\000\000\000\000\017\150\000\000\000\000\000\149\000\149\000\000\000\000\000\000\000\000\000\000\t\177\000\000\000\000\000\000\000\000\000\000\000\000\t\177\000\000\000\000\000\000\000\000\t\177\000\000\000\000\004i\000\000\000\000\004i\000\000\004i\t\177\004i\000\000\004i\000\000\000\000\000\000\004i\004i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\177\004i\000\000\t\177\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004i\004i\000\000\000\000\000\000\000\000\004i\t\177\000\000\t\177\000\000\t\177\000\000\t\177\000\000\000\000\000\000\000\000\t\177\000\000\000\000\t\177\004i\000\000\000\000\004i\000\138\000\000\000\000\000\000\000\000\004i\000\000\000\000\004i\004i\t\177\000\000\000\000\000\000\t\177\000\000\004i\000\000\000\000\004i\004i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004Q\004i\000\000\004Q\000\000\004Q\000\000\004Q\000\000\004Q\000\000\004i\000\000\004Q\004Q\000\000\000\000\000\000\000\000\004i\000\000\000\000\000\000\004i\000\000\000\000\004Q\000\000\000\000\000\000\000\000\000\000\004i\000\000\000\000\000\000\004Q\004Q\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004i\000\000\000\000\004i\004i\000\000\004Q\004i\000\000\004Q\005\210\000\000\004i\004i\000\000\004Q\000\000\004i\004Q\004Q\000\000\000\000\000\000\000\000\000\000\000\000\004Q\000\000\000\000\004Q\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\153\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\153\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\153\000\000\000\000\000\000\000\000\000\000\000\153\000\153\000\000\000\000\004Q\000\000\000\000\004Q\004Q\000\000\000\153\004Q\000\000\n\206\000\000\000\153\004Q\004Q\000\000\000\000\000\000\004Q\0002\0006\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\153\000b\000\000\000f\000j\000n\000\000\0055\000\000\000\000\0055\000\000\000\000\000\000\0055\000\000\0055\017\158\000r\017\186\0055\0055\000\000\000\000\017\198\000\000\000\000\000\000\000\000\000v\000\000\000\000\000\000\000\000\000\153\000\000\000\000\000\000\000\000\000\000\000\000\n\214\000\000\017\222\000\000\000\000\000\000\000\000\000\000\0055\000\130\000\000\000\000\000\153\000\000\018\n\000\000\000\000\0055\000\000\000\000\0055\000\000\0055\000\134\0055\000\000\0055\000\153\000\153\000\000\0055\0055\000\000\002b\000\000\000\000\0055\000\000\000\000\000\000\000\000\000\000\018*\0055\0055\018z\000\000\0055\0055\000\000\000\000\000\000\000\000\0055\0055\000\000\000\000\0055\000\000\0055\018\146\000\000\007\213\000\000\018\158\000\000\018\170\000\000\000\000\000\000\000\000\018\186\000\000\000\000\019j\0055\000\000\000\000\0055\0055\000\000\000\000\000\000\000\000\002b\000\000\000\000\0055\0055\019v\000\000\000\000\000\000\019\142\000\000\0055\000\000\000\000\0055\0055\000\000\001\161\000\000\000\000\001\161\000\000\000\000\000\000\0055\000\000\000\000\0055\0055\000\000\000\000\000\000\000\000\000\000\0055\001\161\0055\0055\000\000\001\161\000\000\0055\0055\000\000\001\161\000\000\0055\000\000\000\000\000\000\001\161\000\000\000\000\001\161\001\161\0055\001\161\001\161\000\000\000\000\000\000\000\000\001\161\000\000\000\000\000\000\001\161\000\000\000\000\001\161\000\000\001\161\001\161\000\000\000\000\0055\000\000\000\000\0055\0055\000\000\000\000\0055\000\000\000\000\000\000\000\000\0055\0055\000\000\000\000\001\161\0055\001\161\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\161\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\161\001\161\0076\000\000\001\161\000\000\000\000\000\000\001\161\000\000\000\000\000\000\n~\000\000\000\000\000\000\000\000\003I\000\000\003I\000\000\000\000\003I\001\161\000\000\001\161\000\000\000\000\000\000\000\000\000\000\007>\001\161\001\161\000\000\001\161\001\161\001\161\003I\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003I\003I\000\000\000\000\003I\003I\000\000\000\000\000\000\000\000\003I\000\000\003I\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003I\003I\000\000\003I\003I\003I\000\000\003I\003I\000\000\003I\000\000\000\000\011\165\000\000\000\000\011\165\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003I\003I\000\000\000\000\003I\000\000\011\165\003I\000\000\000\000\011\165\000\000\000\000\000\000\003Z\003I\000\000\000\000\000\000\000\000\000\000\011\165\000\000\000\000\003I\011\165\003I\011\165\011\165\000\000\000\000\003b\000\000\000\000\003n\000\000\003I\011\165\000\000\000\000\011\165\003I\011\165\000\000\000\000\000\000\000\000\003I\000\000\000\000\003I\000\000\000\000\000\169\000\000\000\000\003I\000\000\000\000\000\000\000\000\000\000\011\165\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\190\000\000\000\000\011\165\000\000\000\000\000\000\000\000\003z\000\000\000\000\000\000\000\226\000\000\t\154\n\198\000\000\t\158\000\000\000\000\000\000\000\169\000\169\000\000\000\000\011\165\011\165\000\000\011\165\000\000\003~\000\169\011\165\000\238\n\206\000\000\n\222\000\000\000\000\000\000\003\134\000\000\t\162\nJ\011\165\000\000\n^\nv\000\000\011\165\011\165\000\000\001\"\000\000\001&\011\165\n\238\000\000\000\000\011\165\011\165\011\165\t\194\001.\000\000\t\198\008^\001:\000\000\t\202\t\206\000\000\t\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\214\000\000\000\169\t\218\000\000\000\000\000\162\000\000\000\226\n\214\t\154\000\000\000\000\t\158\t\226\000\000\000\000\000\000\000\000\000\000\000\000\000\169\000\000\nz\000\000\n\146\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\t\230\000\169\000\169\t\162\nJ\t\234\000\000\n^\nv\000\000\000\000\011r\000\000\001\"\t\238\001&\000\000\000\000\000\000\000\000\001j\000\000\000\000\t\194\001.\000\000\t\198\008^\001:\000\000\t\202\t\206\000\000\t\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\214\000\000\000\000\t\218\000\000\000\000\000\162\000\000\000\226\000\000\t\154\000\000\000\000\t\158\t\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nz\000\000\n\146\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\t\230\000\000\000\000\t\162\nJ\t\234\000\000\n^\nv\000\000\000\000\011\030\000\000\001\"\t\238\001&\000\000\000\000\000\000\000\000\001j\000\000\000\000\t\194\001.\000\000\t\198\008^\001:\000\000\t\202\t\206\000\000\t\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\214\000\000\000\000\t\218\000\000\000\000\000\162\000\000\000\226\000\000\t\154\000\000\000\000\t\158\t\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nz\000\000\n\146\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\t\230\000\000\000\000\t\162\nJ\t\234\000\000\n^\nv\000\000\000\000\004\201\000\000\001\"\t\238\001&\000\000\000\000\000\000\000\000\001j\000\000\000\000\t\194\001.\000\000\t\198\008^\001:\000\000\t\202\t\206\000\000\t\210\000\000\000\000\000\000\000\000\001\137\000\000\000\000\001\137\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\214\000\000\000\000\t\218\000\000\000\000\000\162\001\137\000\000\000\000\000\000\000\000\000\000\000\000\t\226\000\000\001\137\000\000\000\000\000\000\000\000\000\000\001\137\nz\000\000\n\146\000\000\000\000\001\137\001\137\000\000\000\000\000\000\000\000\000\000\t\230\000\000\000\000\001\137\007j\t\234\001\137\007\186\001\137\001\137\000\000\001\189\000\000\000\000\t\238\000\000\000\000\000\000\000\000\000\000\001j\000\000\007r\000\000\000\000\000\000\002\017\000\000\001\137\000\000\001\137\002\017\000\000\000\000\000\000\000\000\000\000\007z\000\000\000\000\002\017\002\017\000\000\007\202\007\210\000\000\000\000\000\000\000\000\002\017\000\000\000\000\000\000\007\154\000\000\000\000\007\130\000\000\007\146\002\017\000\000\001\137\001\137\001\150\000\000\001\137\001\137\000\000\000\000\001\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\162\000\000\002\017\001\137\000\000\000\000\001\137\001\137\000\000\001\137\000\000\000\000\002\017\000\000\002V\001\137\001\137\000\000\001\137\001\137\001\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\017\007\170\000\000\000\000\002\017\000\000\000\000\000\000\007\138\000\000\000\000\000\000\001%\000\000\000\000\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\017\000\000\002\017\000\000\000\000\000\000\000\000\007r\000\000\002\017\002\017\001%\007\218\007\178\002\017\001\013\001%\000\000\001\013\000\000\000\000\000\000\007z\000\000\000\000\001%\001%\000\000\001%\001%\000\000\000\000\000\000\001\013\001%\000\000\000\000\001\013\007\154\000\000\000\000\007\130\001\013\007\146\001%\000\000\000\000\000\000\007z\000\000\000\000\001\013\001\013\000\000\001\013\001\013\000\000\000\000\000\000\000\000\001\013\000\000\000\000\007\162\001\013\001%\000\000\007\130\000\000\007\146\001\013\000\000\000\000\000\000\000\000\001%\0002\0006\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\017*\000^\001\013\000b\001\013\000f\000j\000n\000\000\001%\007\170\000\000\000\000\001%\001\013\000\000\000\000\007\138\000\000\000\000\000r\017.\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\019\146\001%\000\000\001%\001\013\001\013\000\000\000\000\001\013\000\000\001%\001%\007\138\001%\007\178\001%\001\005\000\000\000\000\001\005\000\000\000\130\000\000\000\000\000\000\000\000\018\n\001\013\000\000\001\013\000\000\000:\000\000\000\000\001\005\000\134\001\013\001\013\001\005\001\013\001\013\001\013\001\t\001\005\000\000\001\t\000\000\000\000\000\000\001\005\000\000\000\000\001\005\001\005\000\000\001\005\001\005\000\000\000\000\000\000\001\t\001\005\000\000\000\000\001\t\001\005\000\000\000\000\007\130\001\t\001\005\001\005\000\000\000\162\000\000\001\t\000\000\000\000\001\t\001\t\000\000\001\t\001\t\000\000\000\000\000\000\017>\001\t\000\000\000\000\001\005\001\t\001\005\000\000\007\130\000\000\001\t\001\t\000\000\000\000\000\000\000\000\001\005\0002\tn\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\001\t\000b\001\t\000f\000j\000n\000\000\001\005\001\005\000\000\000\000\001\005\001\t\000\000\000\000\007\138\000\000\000\000\000r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000v\001\005\000\000\001\005\001\t\001\t\000\000\000\000\001\t\000\000\001\005\001\005\007\138\001\005\001\005\001\005\001\025\000\000\000\000\001\025\000\000\000\130\000\000\000\000\000\000\000\000\000\000\001\t\000\000\001\t\000\000\000\000\000\000\000\000\007r\000\134\001\t\001\t\001\025\001\t\001\t\001\t\001\017\001\025\000\000\001\017\000\000\000\000\000\000\007z\000\000\000\000\001\025\001\025\000\000\001\025\001\025\000\000\000\000\000\000\007r\001\025\000\000\000\000\001\017\001\025\000\000\000\000\007\130\001\017\007\146\001\025\000\000\000\162\000\000\007z\000\000\000\000\001\017\001\017\000\000\001\017\001\017\000\000\000\000\000\000\000\000\001\017\000\000\000\000\007\162\001\017\001\025\000\000\007\130\000\000\007\146\001\017\000\000\000\000\000\000\000\000\001\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\017\000\000\001\017\000\000\000\000\000\000\000\000\001\025\001\025\000\000\000\000\001\025\001\017\000\000\000\000\007\138\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\025\000\000\001\025\001\017\001\017\000\000\000\000\001\017\000\000\001\025\001\025\007\138\001\025\001\025\001\025\001\021\000\000\000\000\001\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\017\000\000\001\017\000\000\000\000\000\000\000\000\007r\000\000\001\017\001\017\001\021\001\017\001\017\001\017\001\029\001\021\000\000\001\029\000\000\000\000\000\000\007z\000\000\000\000\001\021\001\021\000\000\001\021\001\021\000\000\000\000\000\000\007r\001\021\000\000\000\000\001\029\001\021\000\000\000\000\007\130\001\029\007\146\001\021\000\000\000\000\000\000\007z\000\000\000\000\001\029\001\029\000\000\001\029\001\029\000\000\000\000\000\000\000\000\001\029\000\000\000\000\007\162\007\154\001\021\000\000\007\130\000\000\007\146\001\029\000\000\000\000\000\000\000\000\001\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\162\000\000\001\029\000\000\000\000\000\000\000\000\001\021\001\021\000\000\000\000\001\021\001\029\000\000\000\000\007\138\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\021\000\000\001\021\001\029\007\170\000\000\000\000\001\029\000\000\001\021\001\021\007\138\001\021\001\021\001\021\007j\000\000\000\000\001-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\029\000\000\001\029\000\000\000\000\000\000\000\000\007r\000\000\001\029\001\029\001-\001\029\001\029\001\029\007j\001-\000\000\001!\000\000\000\000\000\000\007z\000\000\000\000\001-\001-\000\000\001-\007\210\000\000\000\000\000\000\007r\001-\000\000\000\000\001!\007\154\000\000\000\000\007\130\001!\007\146\001-\000\000\000\000\000\000\007z\000\000\000\000\001!\001!\000\000\001!\001!\000\000\000\000\000\000\000\000\001!\000\000\000\000\007\162\007\154\001-\000\000\007\130\000\000\007\146\001!\000\000\000\000\000\000\000\000\001-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\162\000\000\001!\000\000\000\000\000\000\000\000\001-\007\170\000\000\000\000\001-\001!\000\000\000\000\007\138\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001-\000\000\001-\001!\007\170\000\000\000\000\001!\000\000\001-\001-\007\138\007\218\007\178\001-\007j\000\000\000\000\001)\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\000\000\001!\000\000\000\000\000\000\000\000\007r\000\000\001!\001!\001)\001!\007\178\001!\000\000\001)\000\000\000\000\000\226\000\000\t\154\007z\000\000\t\158\001)\001)\000\000\001)\007\210\000\000\000\000\000\000\000\000\001)\000\000\000\000\000\000\007\154\000\000\000\238\007\130\000\000\007\146\001)\000\000\000\000\000\000\000\000\t\162\nJ\000\000\000\000\n^\nv\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\007\162\000\000\001)\000\000\000\000\000\000\t\194\001.\000\000\t\198\008^\001:\001)\t\202\t\206\000\000\t\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\214\001)\007\170\t\218\000\000\001)\000\162\000\000\000\000\007\138\000\000\000\000\000\000\000\000\t\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001)\n\146\001)\000\226\000\000\000\230\000\000\000\000\000\234\001)\001)\t\230\001)\007\178\001)\000\000\t\234\000\000\007\246\000\000\000\000\000\000\001\201\000\000\000\238\t\238\000\000\000\242\000\000\000\000\000\000\001j\000\000\000\254\001\002\000\000\001\n\000\000\t\150\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001*\001.\000\000\0012\0016\001:\000\000\001>\001B\000\000\001F\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001J\000\000\000\000\001N\000\000\000\000\000\162\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001V\000\000\000\000\000\226\000\000\000\230\000\000\000\000\000\234\001Z\007\229\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\229\000\000\000\000\001^\000\000\000\000\000\238\000\000\001b\000\242\000\000\007\229\000\000\007\229\000\000\000\254\001\002\001f\001\n\000\000\000\000\000\000\000\000\001j\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\000\226\000\000\000\230\001*\001.\000\234\0012\0016\001:\000\000\001>\001B\000\000\001F\000\000\014r\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\242\000\000\000\000\000\000\000\000\001J\000\254\001\002\001N\001\n\000\000\000\162\000\000\000\000\000\000\000\000\001\"\000\000\001&\001V\000\000\000\000\000\000\000\000\000\000\000\000\001*\001.\001Z\0012\0016\001:\000\000\001>\001B\000\000\001F\000\000\000\000\000\000\001^\000\000\000\000\000\000\000\000\001b\000\000\000\000\000\000\000\000\000\000\000\000\001J\000\000\001f\001N\000\000\000\000\000\162\000\000\001j\000\000\000\000\000\000\000\000\000\000\001V\000\000\000\000\000\226\000\000\000\230\000\000\000\000\000\234\001Z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001^\000\000\000\000\000\238\000\000\001b\000\242\000\000\000\000\000\000\000\000\000\000\000\254\004\210\001f\001\n\000\000\000\000\000\000\000\000\001j\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001*\001.\000\000\0012\0016\001:\000\000\001>\001B\000\246\001F\000\000\000\000\000\000\007\237\000\000\007\237\000\000\000\000\007\237\000\000\000\000\000\000\000\000\000\000\000\000\001J\000\000\000\000\001N\000\000\000\000\000\162\000\000\000\000\007\237\000\000\000\000\007\237\000\000\001V\000\000\000\000\000\000\007\237\007\237\000\000\007\237\000\000\001Z\000\000\000\000\000\000\000\000\007\237\000\000\007\237\000\000\000\226\000\000\000\230\001^\000\000\000\234\007\237\007\237\001b\007\237\007\237\007\237\000\000\007\237\007\237\000\000\007\237\001f\000\000\000\000\000\000\000\238\000\000\001j\000\242\000\000\000\000\000\000\000\000\000\000\000\254\001R\007\237\001\n\000\000\007\237\000\000\000\000\007\237\000\000\001\"\000\000\001&\000\000\000\000\000\000\007\237\000\000\000\000\000\000\001*\001.\000\000\0012\0016\001:\000\000\001>\001B\003\222\001F\000\000\000\000\000\000\003A\000\000\003A\007\237\000\000\003A\000\000\000\000\007\237\000\000\000\000\000\000\001J\000\000\000\000\001N\000\000\007\237\000\162\000\000\000\000\003A\000\000\007\237\003A\000\000\001V\000\000\000\000\000\000\003A\003A\000\000\003A\000\000\001Z\000\000\000\000\000\000\000\000\003A\000\000\003A\000\000\000\226\000\000\001\022\001^\000\000\001\026\003A\003A\001b\003A\003A\003A\000\000\003A\003A\000\000\003A\001f\000\000\000\000\000\000\000\238\000\000\001j\000\242\000\000\000\000\000\000\000\000\000\000\001\030\003\162\003A\001\n\000\000\003A\000\000\000\000\003A\000\000\001\"\000\000\001&\000\000\000\000\000\000\003A\000\000\000\000\000\000\003\026\001.\000\000\003\030\0016\001:\000\000\003\"\003&\000\000\003*\000\000\000\000\000\000\000\226\000\000\001\022\003A\000\000\001\026\000\000\000\000\003A\000\000\000\000\000\000\003.\000\000\000\000\0032\000\000\003A\000\162\000\000\000\000\000\238\000\000\003A\000\242\000\000\003:\000\000\000\000\000\000\001\030\003\006\000\000\001\n\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\226\000\000\001\022\003>\000\000\001\026\003\026\001.\003B\003\030\0016\001:\000\000\003\"\003&\000\000\003*\003F\000\000\000\000\000\000\000\238\000\000\001j\000\242\000\000\000\000\000\000\000\000\000\000\001\030\0036\003.\001\n\000\000\0032\000\000\000\000\000\162\000\000\001\"\000\000\001&\000\000\000\000\000\000\003:\000\000\000\000\000\000\003\026\001.\000\000\003\030\0016\001:\000\000\003\"\003&\000\000\003*\000\000\000\000\000\000\000\226\000\000\006\130\003>\000\000\006\134\000\000\000\000\003B\000\000\000\000\000\000\003.\000\000\000\000\0032\000\000\003F\000\162\000\000\000\000\000\238\000\000\001j\000\000\000\000\003:\000\000\000\000\000\000\006\138\007\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\003>\000\000\000\000\006\162\001.\003B\006\166\0016\001:\000\000\006\170\006\174\000\000\006\178\003F\000\000\000\000\000\226\000\000\006\130\001j\000\000\006\134\000\000\000\000\000\000\000\000\000\000\006\182\006\186\000\000\000\000\006\190\000\000\000\000\000\162\000\000\000\000\000\238\000\000\000\000\000\000\000\000\006\198\000\000\000\000\000\000\006\138\006\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\006\202\000\000\000\000\006\162\001.\006\206\006\166\0016\001:\000\000\006\170\006\174\000\000\006\178\006\210\000\000\000\000\000\226\000\000\006\130\001j\000\000\006\134\000\000\000\000\000\000\000\000\000\000\006\182\006\186\000\000\000\000\006\190\000\000\000\000\000\162\000\000\000\000\000\238\000\000\000\000\000\000\000\000\006\198\000\000\000\000\000\000\006\138\006\194\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\006\202\000\000\000\000\006\162\001.\006\206\006\166\0016\001:\000\000\006\170\006\174\000\000\006\178\006\210\000\000\000\000\000\226\000\000\t\154\001j\000\000\t\158\000\000\000\000\000\000\000\000\000\000\006\182\006\186\000\000\000\000\006\190\000\000\000\000\000\162\000\000\000\000\000\238\000\000\000\000\000\000\000\000\006\198\000\000\000\000\000\000\t\162\t\174\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\006\202\000\000\000\000\t\194\001.\006\206\t\198\0016\001:\000\000\t\202\t\206\000\000\t\210\006\210\000\000\000\000\000\226\000\000\t\154\001j\000\000\t\158\000\000\000\000\000\000\000\000\000\000\006\182\t\214\000\000\000\000\t\218\000\000\000\000\000\162\000\000\000\000\000\238\000\000\000\000\000\000\000\000\t\226\000\000\000\000\000\000\t\162\t\222\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\t\230\000\000\000\000\t\194\001.\t\234\t\198\0016\001:\000\000\t\202\t\206\000\000\t\210\t\238\000\000\000\000\000\226\000\000\t\154\001j\000\000\t\158\000\000\000\000\000\000\000\000\000\000\006\182\t\214\000\000\000\000\t\218\000\000\000\000\000\162\000\000\000\000\000\238\000\000\000\000\000\000\000\000\t\226\000\000\000\000\000\000\t\162\nJ\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001&\000\000\000\000\000\000\000\000\t\230\000\000\000\000\t\194\001.\t\234\t\198\0016\001:\000\000\t\202\t\206\000\000\t\210\t\238\000\000\000\000\000\000\000\000\000\000\001j\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\182\t\214\000\000\000\000\t\218\000\000\000\000\000\162\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\226\0002\006\022\000F\000J\006.\000N\006F\000R\000V\006J\000Z\000\000\000^\000\000\000b\006N\000f\000j\000n\006R\t\230\000\000\000\000\000\000\000\000\t\234\000\000\000\000\000\000\000\000\000\000\000r\000\000\000\000\t\238\000\000\000\000\000\000\000\000\000\000\001j\000\000\000v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\000\000\000\000\0002\tn\000F\000J\000\000\000N\006F\000R\000V\006J\000Z\000\134\000^\020\146\000b\006N\000f\000j\000n\006R\020\154\001\153\000\000\000\000\001\153\000\000\008b\000\000\000\000\000\000\000\000\000r\000\000\000\000\000\000\007Q\000\000\000\000\000\000\001\153\000\000\000\000\000v\001\153\000\000\000\000\000\000\000\000\000\000\000\162\000\000\000\000\000\000\000\000\001\153\000\000\007Q\000\000\001\153\000\000\001\153\001\153\000\000\000\130\000\000\000\000\007Q\007Q\000\000\000\000\001\153\000\000\007Q\001\153\000\000\001\153\t^\000\134\000\000\0055\000\000\000\000\0055\000\000\000\000\000\000\0055\000\000\0055\000\000\000\000\007Q\0055\0055\000\000\001\153\000\000\000:\000\000\000\000\007Q\007Q\000\000\000\000\000\000\000\000\000\000\001\153\007Q\000\000\000\000\007Q\007Q\000\000\000\000\000\162\000\000\000\000\000\000\003\161\000\000\007Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\153\003\186\007Q\001\153\000\000\000\000\000\000\001\153\0055\000\000\007Q\000\000\000\000\000\000\000\000\000\000\000\000\000\146\000\000\001\153\007Q\000\000\000\000\007Q\001\153\001\153\000\000\000\000\007Q\000\000\003\194\007Q\007Q\000\000\001\153\001\153\001\153\000\000\000\000\000\000\000\000\007Q\000\000\007Q\000\000\000\000\007Q\007Q\004\018\000\000\007Q\004b\000\000\000\000\000\000\007Q\007Q\000\000\000\000\007Q\007Q\000\000\000\000\0055\000\000\000\000\004\026\000\000\000\000\000\000\002\t\000\000\007Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\"\000\000\000\000\000\000\002\t\000\000\004r\004z\000\000\000\237\000\000\007Q\000\237\000\000\007Q\007Q\004B\000\213\000\000\004*\000\213\004:\000\000\007Q\007Q\000\000\000\000\004\026\007Q\000\000\000\000\000\237\000\000\000\000\000\000\000\213\000\000\000\000\000\000\000\213\000\000\004J\004\"\000\000\000\000\000\000\000\237\000\000\000\237\000\237\004\"\000\000\000\000\002\t\000\213\000\000\000\213\000\213\004B\000\000\000\000\004*\000\000\004:\000\000\000\000\000\213\000\000\000\000\004*\000\000\004:\000\000\000\000\000\000\004R\000\000\000\000\002\t\000\000\000\000\000\000\0042\004J\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\213\000\000\000\000\002\t\000\237\000\000\000\000\000\000\002\t\002\t\000\000\000\000\000\213\000\000\000\000\000\000\000\000\000\000\004\130\004Z\002\t\000\000\000\000\000\000\000\000\000\000\004R\000\000\000\000\000\237\000\000\000\000\000\000\0042\000\213\000\000\000\000\000\213\000\000\000\000\000\000\0042\000\000\000\000\000\000\000\237\000\000\000\000\000\000\000\205\000\237\000\237\000\205\000\213\000\000\000\000\000\000\000\000\000\213\000\213\000\237\004Z\000\237\000\000\000\000\000\000\000\000\000\205\000\213\000\213\000\213\000\205\000\209\000\000\000\000\000\209\000\000\000\000\000\000\000\000\000\000\000\000\000\205\000\000\000\000\000\000\000\205\000\000\000\205\000\205\000\209\000\000\000\000\000\000\000\209\000\000\000\000\000\000\000\205\000\000\000\000\004*\000\000\000\205\000\000\000\209\000\000\000\000\000\000\000\209\000\000\000\209\000\209\000\000\000\225\000\000\000\000\000\225\000\000\000\000\000\000\000\209\000\000\000\205\004*\000\000\000\209\000\000\000\000\000\000\000\000\000\000\004\026\000\000\000\000\000\205\000\225\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\209\004\"\000\000\000\000\000\000\000\225\000\000\000\225\000\225\000\000\000\000\000\205\000\209\000\000\000\205\000\000\000\000\000\225\0042\000\000\004*\000\000\004:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\205\000\000\000\000\000\000\000\209\000\205\000\205\000\209\000\000\000\000\000\000\0042\004J\000\000\000\000\000\205\000\205\000\205\000\000\000\000\000\000\000\000\000\000\000\209\000\225\000\000\000\000\000\000\000\209\000\209\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\209\000\209\000\209\000\000\000\000\000\000\000\000\000\000\000\225\000\000\000\000\000\225\000\000\000\217\000\000\0042\000\217\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\225\000\000\000\000\000\000\004\026\000\225\000\225\000\000\000\217\000\221\000\000\000\000\000\221\000\000\000\000\000\225\000\225\000\225\000\000\004\"\000\000\000\000\000\000\000\217\000\000\000\217\000\217\004\026\000\000\000\000\000\000\000\221\000\000\000\000\000\000\000\217\000\000\000\000\004*\000\000\004:\000\000\004\"\000\000\000\000\000\000\000\221\000\000\000\221\000\221\000\000\000\229\000\000\000\000\000\229\000\000\000\000\000\000\000\221\000\000\000\217\004*\000\000\004:\000\000\000\000\000\000\000\000\000\000\004\026\000\000\000\000\000\217\000\229\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004J\004\"\000\000\000\000\000\000\000\229\000\000\000\229\000\229\000\000\000\000\000\217\000\221\000\000\000\217\000\000\000\000\004B\0042\000\000\004*\000\000\004:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\217\000\000\000\000\000\000\000\221\000\217\000\217\000\221\000\000\000\000\000\000\0042\004J\000\000\000\000\000\217\000\217\000\217\000\000\000\000\000\000\000\000\000\000\000\221\000\229\000\000\000\000\000\000\000\221\000\221\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\221\000\221\000\221\000\000\000\000\000\000\000\000\000\000\004R\000\000\000\000\000\229\000\000\004\018\000\000\0042\000\245\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\229\000\000\000\000\000\000\004\026\000\229\000\229\000\000\000\245\004\018\000\000\000\000\000\233\000\000\000\000\000\229\000\229\000\229\000\000\004\"\000\000\000\000\000\000\000\245\000\000\000\245\004z\004\026\000\000\000\000\000\000\000\233\000\000\000\000\000\000\004B\000\000\000\000\004*\000\000\004:\000\000\004\"\000\000\000\000\000\000\000\233\000\000\000\233\000\233\000\000\004\018\000\000\000\000\000\241\000\000\000\000\000\000\004B\000\000\004J\004*\000\000\004:\000\000\000\000\000\000\000\000\000\000\004\026\000\000\000\000\000\245\000\241\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004J\004\"\000\000\000\000\000\000\000\241\000\000\000\241\004z\000\000\000\000\004R\000\233\000\000\000\245\000\000\000\000\004B\0042\000\000\004*\000\000\004:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\245\000\000\000\000\000\000\004R\000\245\000\245\000\233\000\000\000\000\000\000\0042\004J\000\000\000\000\004\130\004Z\000\245\003\153\000\000\000\000\003\153\000\000\000\233\000\241\003\153\000\000\003\153\000\233\000\233\000\000\003\153\003\153\000\000\000\000\000\000\000\000\000\000\000\233\004Z\000\233\000\000\000\000\000\000\000\000\000\000\004R\000\000\000\000\000\241\000\000\000\000\000\000\0042\000\000\000\000\000\000\000\000\000\000\000\000\002-\000\000\000\000\000\000\000\000\000\241\000\000\000\000\000\000\000\000\000\241\000\241\000\000\000\000\000\000\000\000\003\153\000\000\000\000\000\000\000\241\004Z\000\241\000\000\000\000\000\000\000\000\000\000\002-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002-\000\000\000\000\002-\002-\000\000\000\000\000\000\000\000\003Q\003Q\003Q\003Q\002-\003Q\000\000\003Q\003Q\000\000\003Q\000\000\003Q\000\000\003Q\000\000\003Q\003Q\003Q\000\000\000\000\000\000\002-\000\000\000\000\000\000\003\153\000\000\000\170\000\000\000\000\003Q\020\150\000F\000J\002-\000N\006F\000R\000V\006J\000Z\003Q\000^\020\146\000b\006N\000f\000\000\000n\006R\020\154\000\000\000\000\000\000\002-\000\000\000\000\002-\002-\000\000\000\000\000r\003Q\000\000\000\000\000\000\002-\002-\003Q\000\000\000\000\002-\000v\000\000\000\000\000\000\003Q\000\000\0002\000\142\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000r\000\000\000\000\000\000\000\000\003Q\000\000\000\000\000\000\000\000\000\000\000v\0002\000\142\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000\000\000\130\000\000\000\000\000\000\000\000\000\000\000\158\000\000\003\161\000\000\000\000\000r\000\000\003Q\000\134\000\000\0002\005\030\000F\000J\000\000\000N\000v\000R\000V\000\000\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000r\000\000\000\158\000\000\000\000\000\162\000\000\000\000\000\000\000\000\000\134\000v\000\000\0002\005\030\000F\000J\000\000\000N\000\000\000R\000V\000\166\000Z\000\000\000^\000\000\000b\000\000\000f\000j\000n\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000r\011\001\000\134\000\000\000\162\000\000\005\"\005&\000\000\011\137\000\000\000v\0002\000\142\000F\000J\000\000\000N\000\000\000R\000V\000\166\000Z\000\000\000^\000\000\000b\011\137\000f\000j\000n\000\000\000\130\000\000\000\000\n\002\000\000\000\000\000\000\000\000\000\000\000\000\011\137\000r\002)\000\000\000\134\000\000\011\137\011\137\005\"\005&\n\n\000\000\000v\n\022\000\000\005*\011\137\000\000\000\000\011\137\000\000\011\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\000\000\000\000\158\000\000\011\137\000\000\000\000\000\000\000\000\000\000\000\134\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\"\0052\0002\005\030\000F\000J\000\000\000N\000\000\000R\000V\000\000\000Z\000\000\000^\000\000\000b\011\137\000f\000j\000n\000\000\n&\000\000\011\137\000\000\000\000\000\162\000\000\000\000\000\000\000\000\n.\000r\000\000\000\000\011\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000v\000\000\000\000\000\000\000\000\000\000\000\000\011\137\011\137\000\000\0002\005\030\000F\000J\000\161\000N\000\000\000R\000V\000\000\000Z\000\130\000^\002!\000b\000\165\000f\000j\000n\000\000\000\000\000\000\n\190\000\000\000\000\000\134\000\000\000\000\000\000\0212\005&\000r\000\000\n\190\000\000\000\000\000\000\n\198\000\000\000\000\000\000\000\000\000v\000\161\000\161\000\000\000\000\000\000\n\198\000\000\000\000\000\000\000\173\000\161\000\165\000\165\n\206\000\000\n\222\000\000\000\000\000\000\000\000\000\130\000\165\000\000\000\000\n\206\000\000\n\222\n\190\000\000\000\000\000\000\000\000\n\182\000\000\000\134\000\161\000\000\0216\0212\005&\000\000\000\000\n\198\000\000\000\000\000\000\n\238\000\000\000\173\000\173\n\190\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\230\000\000\000\000\n\206\000\000\n\222\000\000\n\198\000\000\000\000\000\000\000\161\000\000\000\189\011\014\000\000\000\000\000\000\n\214\000\000\000\000\n\182\000\165\n\230\000\000\n\238\n\206\000\000\n\222\n\214\000\161\021>\n\182\000\000\000\000\000\000\000\000\000\000\000\000\n\190\000\000\000\165\000\000\000\000\000\000\000\161\000\161\000\000\n\238\000\000\n\190\000\000\000\000\000\000\n\198\000\000\000\165\000\165\000\000\n\246\000\177\000\177\000\000\000\000\000\000\n\198\n\214\000\000\000\000\000\000\n\230\000\185\011\014\n\206\000\000\n\222\000\000\000\000\000\173\000\000\000\000\n\230\n\246\000\000\n\206\000\000\n\222\000\000\000\000\n\214\000\000\000\000\000\000\000\173\000\173\n\238\000\000\000\000\000\000\000\000\000\000\000\189\000\000\000\000\000\000\000\000\n\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\022\n\254\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\246\000\000\000\000\000\000\000\000\000\000\000\000\n\214\000\000\000\000\000\000\n\246\000\000\000\000\000\000\000\000\000\000\000\000\n\214\000\177\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\185\000\000\000\000\000\000\000\177\n\254\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\185\n\254"))
let lhs =
- (16, "\000\012\000\011\000\n\000\t\000\008\000\007\000\006\000\005\000\004\000\003\000\002\000\001\000\000\001\004\001\004\001\004\001\003\001\003\001\003\001\003\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\255\000\254\000\254\000\254\000\254\000\253\000\252\000\252\000\252\000\251\000\251\000\251\000\250\000\250\000\250\000\249\000\249\000\249\000\248\000\247\000\246\000\245\000\245\000\244\000\244\000\243\000\243\000\242\000\242\000\241\000\241\000\240\000\239\000\239\000\238\000\238\000\237\000\237\000\237\000\236\000\236\000\235\000\234\000\233\000\232\000\231\000\230\000\229\000\228\000\227\000\226\000\225\000\224\000\223\000\223\000\222\000\222\000\221\000\221\000\220\000\220\000\219\000\219\000\219\000\218\000\218\000\218\000\218\000\218\000\217\000\217\000\216\000\215\000\215\000\215\000\215\000\214\000\214\000\213\000\212\000\211\000\211\000\211\000\210\000\210\000\210\000\209\000\209\000\209\000\209\000\208\000\208\000\208\000\208\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\207\000\206\000\205\000\205\000\204\000\204\000\204\000\203\000\203\000\202\000\202\000\202\000\201\000\201\000\200\000\199\000\198\000\198\000\197\000\197\000\196\000\196\000\195\000\195\000\194\000\194\000\193\000\192\000\191\000\191\000\190\000\190\000\189\000\188\000\188\000\188\000\188\000\187\000\186\000\185\000\185\000\184\000\183\000\183\000\182\000\182\000\182\000\182\000\182\000\181\000\181\000\181\000\181\000\180\000\180\000\180\000\180\000\179\000\179\000\179\000\179\000\178\000\177\000\177\000\176\000\176\000\176\000\175\000\174\000\174\000\174\000\174\000\173\000\172\000\172\000\172\000\172\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\171\000\170\000\170\000\169\000\169\000\168\000\168\000\167\000\167\000\166\000\166\000\166\000\166\000\165\000\165\000\165\000\164\000\164\000\164\000\164\000\164\000\164\000\164\000\163\000\162\000\162\000\162\000\161\000\160\000\160\000\159\000\159\000\158\000\158\000\157\000\157\000\156\000\156\000\155\000\155\000\154\000\154\000\154\000\154\000\154\000\154\000\154\000\153\000\152\000\151\000\151\000\150\000\150\000\149\000\149\000\148\000\148\000\147\000\147\000\146\000\146\000\145\000\145\000\144\000\144\000\143\000\143\000\142\000\142\000\141\000\141\000\140\000\140\000\139\000\139\000\138\000\138\000\137\000\137\000\136\000\136\000\135\000\135\000\134\000\134\000\133\000\133\000\132\000\132\000\131\000\131\000\130\000\130\000\129\000\129\000\128\000\128\000\127\000\127\000~\000~\000}\000}\000|\000|\000{\000{\000z\000z\000y\000y\000x\000x\000w\000v\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000u\000t\000s\000r\000q\000p\000o\000n\000m\000l\000k\000k\000k\000j\000j\000j\000i\000i\000i\000h\000g\000f\000e\000d\000c\000b\000b\000b\000a\000a\000a\000`\000`\000_\000_\000_\000^\000^\000]\000\\\000\\\000\\\000[\000Z\000Z\000Y\000Y\000X\000X\000W\000W\000V\000V\000U\000U\000T\000T\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000S\000R\000R\000Q\000Q\000P\000P\000O\000O\000N\000N\000N\000N\000N\000M\000M\000L\000L\000L\000L\000K\000J\000I\000I\000I\000H\000H\000H\000G\000G\000G\000G\000G\000F\000F\000F\000F\000F\000E\000E\000E\000E\000E\000E\000E\000D\000D\000D\000D\000D\000D\000D\000C\000C\000C\000C\000C\000C\000C\000B\000B\000B\000B\000B\000B\000B\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000>\000>\000>\000>\000>\000>\000>\000>\000>\000>\000>\000>\000>\000=\000=\000=\000=\000=\000<\000;\000;\000;\000;\000;\000:\0009\0008\0007\0006\0005\0005\0005\0005\0005\0005\0005\0004\0004\0004\0003\0002\0002\0001\0001\0000\0000\000/\000/\000.\000.\000-\000-\000,\000,\000+\000+\000*\000*\000)\000)\000(\000(\000'\000'\000&\000&\000%\000%\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000$\000#\000#\000#\000\"\000\"\000\"\000\"\000!\000!\000!\000!\000!\000 \000\031\000\031\000\031\000\030\000\030\000\029\000\028\000\028\000\028\000\028\000\027\000\027\000\027\000\026\000\026\000\025\000\025\000\025\000\024\000\024\000\024\000\023\000\023\000\023\000\022\000\022\000\021\000\021\000\021\000\021\000\021\000\021\000\021\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\019\000\019\000\019\000\019\000\019\000\019\000\019\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\017\000\017\000\017\000\017\000\017\000\016\000\016\000\015\000\014\000\013\000\013\000\013")
+ (16, "\000\012\000\011\000\n\000\t\000\008\000\007\000\006\000\005\000\004\000\003\000\002\000\001\000\000\001\005\001\005\001\005\001\004\001\004\001\004\001\004\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\000\255\000\255\000\255\000\255\000\254\000\253\000\253\000\253\000\252\000\252\000\252\000\251\000\251\000\251\000\250\000\250\000\250\000\249\000\248\000\247\000\246\000\246\000\245\000\245\000\244\000\244\000\243\000\243\000\242\000\242\000\241\000\240\000\240\000\239\000\239\000\238\000\238\000\238\000\237\000\237\000\236\000\235\000\234\000\233\000\232\000\231\000\230\000\229\000\228\000\227\000\226\000\225\000\224\000\224\000\223\000\223\000\222\000\222\000\221\000\221\000\220\000\220\000\220\000\219\000\219\000\219\000\219\000\219\000\218\000\218\000\217\000\216\000\216\000\216\000\216\000\215\000\215\000\214\000\213\000\212\000\212\000\212\000\211\000\211\000\211\000\210\000\210\000\210\000\210\000\209\000\209\000\209\000\209\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\208\000\207\000\206\000\206\000\205\000\205\000\205\000\204\000\204\000\203\000\203\000\203\000\202\000\202\000\201\000\200\000\199\000\199\000\198\000\198\000\197\000\197\000\196\000\196\000\195\000\195\000\194\000\193\000\192\000\192\000\191\000\191\000\190\000\189\000\189\000\189\000\189\000\188\000\187\000\186\000\186\000\185\000\184\000\184\000\183\000\183\000\183\000\183\000\183\000\182\000\182\000\182\000\182\000\181\000\181\000\181\000\181\000\180\000\180\000\180\000\180\000\179\000\178\000\178\000\177\000\177\000\177\000\176\000\175\000\175\000\175\000\175\000\174\000\173\000\173\000\173\000\173\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\172\000\171\000\171\000\170\000\170\000\169\000\169\000\168\000\168\000\167\000\167\000\167\000\167\000\166\000\166\000\166\000\165\000\165\000\165\000\165\000\165\000\165\000\165\000\164\000\163\000\163\000\163\000\162\000\161\000\161\000\160\000\160\000\159\000\159\000\158\000\158\000\157\000\157\000\156\000\156\000\155\000\155\000\155\000\155\000\155\000\155\000\155\000\154\000\153\000\152\000\152\000\151\000\151\000\150\000\150\000\149\000\149\000\148\000\148\000\147\000\147\000\146\000\146\000\145\000\145\000\144\000\144\000\143\000\143\000\142\000\142\000\141\000\141\000\140\000\140\000\139\000\139\000\138\000\138\000\137\000\137\000\136\000\136\000\135\000\135\000\134\000\134\000\133\000\133\000\132\000\132\000\131\000\131\000\130\000\130\000\129\000\129\000\128\000\128\000\127\000\127\000~\000~\000}\000}\000|\000|\000{\000{\000z\000z\000y\000y\000x\000w\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000v\000u\000t\000s\000r\000q\000p\000o\000n\000m\000l\000l\000l\000k\000k\000k\000j\000j\000j\000j\000i\000h\000g\000f\000e\000d\000c\000c\000c\000b\000b\000b\000a\000a\000`\000`\000`\000_\000_\000^\000]\000]\000]\000\\\000[\000[\000Z\000Z\000Y\000Y\000X\000X\000W\000W\000V\000V\000U\000U\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000T\000S\000S\000R\000R\000Q\000Q\000P\000P\000O\000O\000O\000O\000O\000N\000N\000M\000M\000M\000M\000L\000K\000J\000J\000J\000I\000I\000I\000H\000H\000H\000H\000H\000H\000G\000G\000G\000G\000G\000F\000F\000F\000F\000F\000F\000F\000E\000E\000E\000E\000E\000E\000E\000D\000D\000D\000D\000D\000D\000D\000C\000C\000C\000C\000C\000C\000C\000B\000B\000B\000B\000B\000B\000B\000B\000B\000B\000B\000B\000B\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000A\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000@\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000?\000>\000>\000>\000>\000>\000=\000<\000<\000<\000<\000<\000;\000:\0009\0008\0007\0006\0006\0006\0006\0006\0006\0006\0005\0005\0005\0004\0003\0003\0002\0002\0001\0001\0000\0000\000/\000/\000.\000.\000-\000-\000,\000,\000+\000+\000*\000*\000)\000)\000(\000(\000'\000'\000&\000&\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000%\000$\000$\000$\000#\000#\000#\000#\000\"\000\"\000\"\000\"\000\"\000!\000 \000 \000 \000\031\000\031\000\030\000\029\000\028\000\028\000\028\000\028\000\027\000\027\000\027\000\026\000\026\000\025\000\025\000\025\000\024\000\024\000\024\000\023\000\023\000\023\000\022\000\022\000\021\000\021\000\021\000\021\000\021\000\021\000\021\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\019\000\019\000\019\000\019\000\019\000\019\000\019\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\017\000\017\000\017\000\017\000\017\000\016\000\016\000\015\000\014\000\013\000\013\000\013\000\013\000\013")
let goto =
- ((16, "\0009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\025\000\000\0011\001\020\000\000\000\163\000U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001n\000\000\008^\000Y\000U\000\000\000\000\000\000\000\000\000\000\000\000\008\200\000s\012t\000\000\000\000\000\000\021\224\000\000\000\132\000\000\000\000\001\015\000\019\000\000\000\000\000h\000\000\0002\000\0001\\\003\162%\230$@\000h\000\000\005\\\000\000\011\026\011\164\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\250%\230\000\000\000\000\004\008\000\000\006r\000\000\008\014\000\000\000\000\000\000\000\000\000\170\000\000 \240\000\000\000\000\003\030\000\000\018Z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\224\000\000\000\000\0132\000\000\016r\000\000\"\164\000\000#\162\000\0007,\000\0007\218\000\0007\224\000\0007\244\000\0007\250\000\000\014\192\000\000\031\198\000\000\000\000\000\000\000\000\000\0008\000\000\0008\014\000\0008\"\000\000\022h\000\000\000\000 4\000\000\000`\000U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000D\001\024\000\000\000\234\000\000\000\000$\248\000\0001\224\000\000\000\000\000\000\001J\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000g1\230\000\000\001\168\000\000\000\000&\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\212&\020\000\000\018\180\000\000\025\180\027x\000\000\000\000\000\000\002\164\000\000!~\000\000\000\0001\254\000\000\000\000\000\000\002\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000&\144\000\000\nb\000\000\000\000\000\000$\148\000\000'R\000\000\000\000\000\000\000\000\001\198\000\000\000\0002~\000\000\000\000\000\000\021\134\002\028\000\000\000\000\000\000\000\000\000\000\000\000\004\196\000\000\017`\000\000 \214\000\000!\030\000\000*d\000\000+\206\000\0000\200\000\0001\198\000\0003\156\000\0008N\000\000\019~\000\000\027n\000\0008|\000\0008\158\000\0008\180\000\000\000\000\000\000\000\000\000\000\002\132\t~\000\000\003P\000\000\000\000\000\000\000\021\000\000\000\000\000\000\007\242\000\000\000\000'\002\000\000\000\000\000\000\000\000\000\000\000\000\000.\000\000\000\000\000\000\002\n\000\000\000\000\000\000\000\174\000\000\000\000\028\220\000Y\000\000\000\000\001\194\002\168\000\000\000\000\000\000\000\000\000\000\004N\000\000\"\168\000\000\000\017\000\000\000\000\004v\000\000\000\000\000\000\000\000\000\000\000\000%\016\000\000\000\000\000\000\001\202\000\000\000\000\000\000\000\000\005\254\029R\000\000\002\144\000\000\000\000\004\150\002\234\000\000\000\000\000\000\000\000\012\254\000\000\000\000\000\000\000\000\000\000\000\000\000\165\0128\000\000\013\230\000\000\000\000\000\000\004 \000\000\013\"\000I\000\000%\174\000\000\000\000\000\000\014\016\002\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\132\000\000\021X\000\0002\156\000\000\000\000\001X\000\000\007d\000\000\015\196\003\190'\128\000\000\000\000\000\000\000\140\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\216'\128\000\000\019`\000\000\021\016\023\176\000\000\000\000\000\000\004z\000\000!\148\000\000\000\0003\014\000\000\000\000\000\000\004\144\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0005l\000\0005\134\000\000\000\000\000\000\004b\000\000\000\000\000\000\000\000\000\000\000\000\030P\000\000\031\128\000\000)Z\000\000*\202\000\0001\206\000\0008j\000\0008\198\000\0008\220\000\0008\254\000\0009$\000\000\024\142\000\000\024D\000\0009n\000\0009\156\000\0009\172\000\000'\244\000\000\000\000\000\0003\140\000\000\000\000\000\000\002x\000*\000\000\024\192\000#\003\150\000\000\005\224\000\000\013\210\000\214\007\222\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0004\008\000\000(t%\196\004\148\000\000\000\000\000\000\031B\000\000(\160\000\000)\198\000\000(\230)B\004\030\000\251\005<\000\000\000\000\000\000\000P\000\000\000\000\003\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0004*\000\000\000\000\000\000\000\000\000\000\":\000\000)z\000\000\000\000\000\000\000\000\000\000\000\000\014\194\000\000\007\136\000\000\000\000\000\000\000\000\024\156\002\188\000\000,\222\000\000\000\000\000\000\002\224\000\000\000\000+\246\001\232\000\000\008,,8\000\000\000\000)\244\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\013^)\244\000\000\028\140\000\000\028\204\029\140\000\000\000\000\000\000\005Z\000\000#V\000\000\000\0004z\000\000\000\000\000\000\005\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000*p\000\000\021J\000\000\000\0004\158\000\0004\194\000\000\000\000\004|\004(\000\000\000\000,\232\000\000\000\000\000\000\006\030\000\0004V\000\000\000\0005\244\000\000\000\000\000\000\006\252\000\000\007\238\000\000\"8\000\000-.\000\0004\200\000\0005J\000\0009\142\000\000:\012\000\000:\026\000\000:.\000\000::\000\000:\130\000\000:\166\000\000\000\000\000\000\000\000\000\000\000\000\nl\000\000\n\n\000\000\012\236\012\132\000\000\018H\000\000\000\000\000\000\000\000\000\000\000\0006\024\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\003*\000\000\000\0000\230\000\000\000\000\000\000-R\000\000\000\000\000\202\000\000\000\000\000\0006\012\000\000\000\000\000\000\000\000-h\000\000\000\000\000\000\000\000\004\180\003$\000\000-\156\000\000\000\000\000\000\000\000\025@\005\006\000\000\025\192\000\000\000\000\006&\000\000-\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\148\000\000\000\0006\020\000\000\000\000\000\000.&\000\000\000\000\005 \000\000\000\000\015r\000\000\026\132\000\000\000\000#\132\000\000\000\000\000\000\004H\000\000\000\0006*\000\000\000\000\000\000\000\000.Z\000\000\000\000\000\000\000\000\0068\008r\000\000.\218\000\000\000\000\000\000\000\000\000\000\000\000\015\238\000\000\000\000\005\"\000\000\016\186\000\000\004H\000\000\000\000\004\194\016j\000\000\005\180\000\000\000\000\000\000\000\000\004b\000\000*\232\000\000\027\004\000\t\027\132\000\000\000\188\000\000\0176\000\000\017\178\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\216\028\004\000\242\028\132\000\000\000\000\000\000\005\128\000\000\018~\000\000\006\006\000\000\000\000\006\020\003:\029\132\000\000\004\134\000\000\018\250\0302\000\000\000\000\019v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006P\008\170\000\000\006\174\000\000\000\000\000\000\000\000\005|\000\000\020B\000\000\000\000\000\000\031\1784\248\000\000\000\000\000\000\0312\000\000\000\000\000\000\000\000\0252\004\234\000\000\000\000.\240\000\000\000\000\000\000\000\000\006\016\000\000\000\0006<\000\000\000\000\000\000/$\000\000\000\000\005\170\000\000\000\000/D\000\000\000\000\006\178\006\026\000\000\000\000/p\000\000\000\000\006\240 v\000\000\007j\000\000\000\000/\174\000\000\000\000\000\000\000\000\000\000\000\000\007\148\000\000\000\0006\162\000\000\000\000\000\000/\206\000\000\000\000\000\000\000\000\000\000$\018\000\000\000\000\000\000\004\130\000\000\000\000\000\0000>\000\000\000\000\008\240\008:\000\000\000\0000\212\000\000\000\000\007\016\000\000\000\000\000\000\000\000\004b\004\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005,\000\000\020\190\000\000\000\000\000\00056\000\000\tb\000\000\000\000\000\000\005\208\000\000\000\000\004\168\021n\000\000\022Z\000\000\000\000\000\000\007P\000\000\022n\007h\023h\000\000\025n\000\000\000\000\000\000\007\186\000\000+Z\007\198+r\000\000+\238\000\000\000\000\000\000\007\242\000\000\025\170\008R\000\000\000\000\002\014\006&\008\178\008\004\000\000\028\234\000\000\000\000\000\000\008\200\000\000#\238\008\218\000\000\000\000\000\000\003D\000\000\000\000\000\000\000\000\000\000\003\174\000\000\000\000\004\020\000\000\000x\000\000\000\000\000\000\004\254\000\000\000\000\000\000\000\000\000/\000\000\006\186\004\140\000\178\000\000\000\000\003\134\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001J\000\136\000\000\000\000\002\150\000\000\000\000\000\000\008\008\000\000\000\000\011\006\012\224\000\000\000\000\000\000\000\000\0146\014\188\000\246\000\000\015\172\000\000\000\000\000\000\000\000\000\000\000\000\004\238\000\000\000\000\008\232\000\000\000\000\004\190\000\000\000\000\000V\000\000\000\000\000=\000\000\006\218\005\136\002\240\000\000\000\000\0026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\162\016\n\000\000\000\000\000\000\000\000\006\208\000\000\000\000\tL\000\000\000\000\000\000\017\196\000\000\000\000\000B\021P\004\176\000\000\021\210\000\000\000\000\000\000\000\000\000\000\000\000\0003\000\000\007H\003\\\001\n\000\000\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\000\000\000\000\005\190\000\000\000\000\000%\000\000\007|\005\230\0050\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\188\000\000\000\000\012H\022\132\000\000\000\000\000\000\000\000\000\242\000\000\004\254\000\000\008h\000\000\000\000\000\000\000\000\000\000\000\000\019\148\nf\000\000\000\000\011\192\000\000\000\000\000\000\000\000\006b\000\000\012\024\000\000\000\000\000\000\000\000\003\240\000\000\000\000\000\000\000y\000\000\000\000\000\205\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\236\005P\000\000\000\000\000\000\028\194\000\000\000\000\013\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000}\000\000\000\000\000\000\000\000\000\000\000Z\002\150\000Y\004\168\n\166\005\196\000\000\000\000\005\218\007\206\008\188\008\202\000\000\000\000\000\000\000\000\000\000\000\000\000\000\013\238\005\218\030\204\006\190\000\000\000\000\t\030\000\000\023<\000\000\000\000\006\166\000\000\000\000\000\000\004\208\000\000\001B\000\000\006\024\015\"\000\000\000\000\000\000\000\000\004N\000\000\004v\000\000\007d\000\000\000\000\001R\000\000\000\000\000\000\000\000\n.\000\000\000\000\005\218\t*\000\000\023\252\000\000\004H\006\216\000\000\000\000\000\000\000\000\000\000\003$\000\000\000\000\000\000\000\000\000\0001v\008\148\000\000\000c\000\000\000\000\000\000\000\000\000\000\002\030\n\170\001\164\011&\000\000\002\154\012\166\000\000\006\198\000\000\003\022\000\000\004\154\000\000\005\020\000\000\000\000\000\000\000\000\000\000\008\160\000\000\005\224\000\000\t^\000\000\006\152\000\000\004H\007*\000\000\003\166\000\000\000\000\000\000\006,\007P\006>\000\000\008\136\000\000\008\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\234\000\000\tn\000\000\000\000\000\000\000\000\000\000\006\140\007\232\007\226\000\000\007\250\000\000\000\000\000\181\t\182\000\000\006\232\000\000\000\000\000\000\000\000\0074\000\000\000\000\000\000\000\000\000\000\0074\008t\002\134\007\128\007\210\000\000\000\000\t\202\000\000\000\000\000\000\000\000\t\002\000\000\000\000"), (16, "\001\182\001\205\0046\0006\000\n\005\001\005\002\000\\\000\\\000\017\004\136\000q\000e\000-\001;\004L\004\179\002S\003T\003<\002+\004\198\000-\005m\000^\005\006\005n\004\134\000\t\004\137\004Y\003V\004J\004\177\004\180\004Y\004M\004Y\004\196\005\182\000D\004\199\004Y\003\007\005\023\001\184\000\017\005\024\000\016\001\185\000^\000^\000\191\002\219\000\017\000_\000_\004\252\004\253\000`\000`\001\129\001\182\001\205\000-\005\028\0006\000D\005.\000\\\003\243\0019\002,\0018\004\176\000-\001U\001\131\005r\005/\0051\003\006\005\021\004\133\000i\000i\000\193\001\182\001\203\004Z\001O\004\177\004\180\004Y\004Z\003\131\004Z\001\210\004I\001%\004\134\004Z\004\137\004Y\0012\003\007\000'\001\184\000&\005\191\004a\001\185\000^\001t\000'\004J\000\005\000_\001<\004M\004Y\000`\005\021\004\194\001\182\001\205\0006\004b\004Y\003V\000^\000E\001\184\004P\002B\005\021\001\185\000-\001\135\000\008\000\t\002S\003T\003<\001\198\0006\000i\0006\002[\002G\0059\000-\004Z\002H\001@\003\014\003h\001\199\003\133\003b\004\195\002\237\004Z\001@\000j\000j\003\015\003\007\000-\001\184\003P\005:\001=\001\185\003^\001P\0007\004\196\004\184\004Z\004\199\004Y\004s\004Y\000\137\002-\002L\004Z\000k\000k\003=\000-\003\\\004\185\004=\000-\002B\003\"\000\154\000-\000\160\003s\001W\0034\001\214\000\169\001\198\001X\004Q\000\160\001Y\002G\000\166\000-\000\138\002H\001@\003\014\005<\001\199\003c\001\210\002\220\001%\001\215\0006\000j\005=\005W\001\216\000\168\001\198\005X\001\217\001/\000m\0007\002,\001\218\000\139\004Z\004\224\004Z\000\140\001\199\005u\005N\004\230\002L\000o\000k\000\160\003\029\005Z\005N\000b\003\244\0007\002B\003\"\004\209\002u\000\160\005\\\002\142\0034\001\214\000\170\001\198\004\149\000\\\0007\003Y\002G\000\185\002\238\001<\002H\001@\003\014\003\246\001\199\001>\003e\004[\004\240\001\215\005\131\001\182\001\205\003\015\001\216\000\152\000-\003P\001\217\004e\002S\003j\001%\001\218\000-\004\186\001E\002A\005/\005s\003\006\002w\000\152\002L\001\204\002x\000^\003=\000\191\003\\\002\243\000_\004T\004\001\003\"\000`\004(\000\160\003s\004\143\0034\001\214\002\007\002\008\003\007\001@\001\184\002\247\000\179\000\152\001\185\000\160\004\227\001@\000\166\005\133\004\141\005F\004\188\004\228\000i\001\215\000\192\001\182\001\205\005F\001\216\000\152\000\160\001|\001\217\000\166\000\252\004\185\000-\001\218\000-\004\189\005 \001\143\005/\005x\003<\000-\001c\005Q\004d\005R\001e\005I\004\133\000\160\005J\005P\000\166\000\160\004\227\005I\000\166\000\160\005J\0006\000\166\004b\004Y\005\134\003\007\004\134\001\184\004\137\004Y\0006\001\185\000\160\001'\000\255\000\166\001\145\002\133\002\193\002\214\002\196\005\130\000^\001A\001\182\001\205\002\161\002[\000\\\004\003\002\134\004\140\000g\0006\002B\000\253\001N\000-\001*\000j\0006\005/\005x\003<\001\198\0006\001@\003\014\004\141\002G\001O\002\199\000\017\002H\001@\003\014\005\136\001\199\003\015\003\249\003u\002[\004Z\000k\005\196\005=\005W\003\007\004Z\001\184\005\138\000^\001,\001\185\0006\001d\000_\0006\000\253\001d\000`\004\186\004)\005}\002\007\002\008\002L\005d\005e\003\"\003\029\005\140\000\160\003'\000\\\0034\002B\003\"\000e\002\164\000\160\005\142\004\185\0034\001\214\000i\001\198\004S\001\182\001\205\0007\002G\000'\002\165\005!\002H\001@\003\014\005~\001\199\000\216\003\127\0006\001@\001\215\005-\005$\005=\005W\001\216\0006\005\148\002J\001\217\005\191\001P\002U\000^\001\218\005\149\001*\005i\000_\000\225\004_\000\\\000`\004;\002L\000\182\0007\000^\003=\001\184\005\128\0007\001m\001\185\002B\003\"\000\160\002u\000\160\003'\002\142\0034\001\214\001X\001\198\000\160\001Y\000i\000\166\002G\001+\004\155\004\248\002H\001@\003\014\005~\001\199\004Q\004<\0007\000j\001\215\0007\000^\005=\005W\001\216\001#\000_\002J\001\217\002\\\000`\005\021\0006\001\218\001q\002\n\002u\002A\001\210\002\142\002[\002w\000k\002L\004\191\002x\002\221\003=\004B\005\128\004\144\001\182\001\205\002\237\003\"\000i\0006\000\160\003'\003u\0034\001\214\000-\002\251\000-\002.\002\226\000l\005/\005x\003<\000-\000\211\0007\000\236\005 \0006\000-\0006\002A\002\255\001\215\002\237\002w\000j\001\198\001\216\002x\000m\0006\001\217\0006\001p\000\149\003\007\001\218\001\184\005\193\001\199\0020\001\185\004\250\000o\000\188\004\170\004Y\000-\002\250\000k\000\191\005\127\001\212\001\182\001\205\003\003\000^\001\132\004=\000\213\003\018\003x\000^\000\214\003\004\004|\000-\001*\003\028\003B\005/\005x\003<\001\131\000\138\0006\000j\003\004\003\004\002\133\002\193\002\194\002\196\002.\001\213\004G\001\214\004V\002\161\000\211\000\227\000\238\002\134\004\140\003K\000m\003\007\003\248\001\184\000\139\000k\001,\001\185\000\140\0007\004Z\001\215\001^\003)\000o\004\141\001\216\005\129\002\199\003\142\001\217\0006\0021\0022\0024\001\218\002\133\004\011\003\004\002\209\003h\002B\001Z\003M\001\187\002\161\0006\000^\0007\002\134\000\213\001\198\003)\004\013\000\214\001\196\002G\002\027\004\130\000\169\002H\001@\003\014\005~\001\199\003.\002\007\002\008\005!\004\146\001\182\001\205\005=\005W\000\169\004\195\002\164\002J\000\243\005,\005$\000\227\0032\000-\005'\000\228\002\237\005/\005x\003<\002\165\005?\004\196\002L\003\221\004\199\004Y\003=\000-\005\128\0007\001j\002B\000\152\003\"\000\160\0006\000\160\003'\005\018\0034\001\214\001\198\003\007\000\160\001\184\004\204\002G\002\164\001\185\000\160\002H\001@\003\014\005~\001\199\002[\000-\0004\005\137\003K\001\215\002\165\005=\005W\002[\001\216\0006\002J\002\237\001\217\002*\0006\000\\\0006\001\218\003\159\000\181\0006\000\160\004}\003p\000\166\001\001\002L\004Z\002z\0035\003=\004\176\005\128\000\228\001\182\001\205\003L\003\"\004\128\001\006\000\160\003'\005\019\0034\001\214\000\244\003p\000-\004\177\004\180\004Y\005/\005x\003<\003m\001*\002\t\003r\000^\000\246\000-\005\"\0053\000_\001\215\004\004\004\202\000`\0007\001\216\000\\\003\004\002\238\001\217\000q\005u\002B\003\007\001\218\001\184\003q\001\000\003\136\001\185\002u\004\133\001\198\002\142\002\131\001,\003\183\002G\000i\005\141\003\246\002H\001@\003\014\005~\001\199\005K\001\001\004\134\005+\004\137\004Y\001\002\005=\005W\004Z\001\003\001@\002J\000^\003\177\001\004\003\138\005{\000_\0007\004W\0007\000`\001B\0007\003)\002\158\000^\002L\003\136\0007\002w\003=\004\207\005\128\002x\001\182\001\205\004\147\003\"\000\169\005b\000\160\003'\005\144\0034\001\214\000i\005\172\000-\002\007\002\008\005;\002S\003T\003<\004X\000\160\001l\001s\001o\003\233\004\003\003\137\004Z\003\167\001\215\003.\002B\005\151\003\184\001\216\000j\005\170\004\148\001\217\003\008\003\233\001\198\003\007\001\218\001\184\0006\002G\0032\001\185\000\160\002H\001@\003\014\005~\001\199\005L\003\012\004\192\003\235\000k\001\182\001\205\005=\005W\000\169\004\195\0006\002J\002u\005'\000\211\002\142\000\238\000-\003\234\005\173\005\019\002S\003T\003<\004\245\004\205\004\196\002L\000\\\004\199\004Y\003=\000]\005\128\000j\002\133\000-\004\193\003\"\005\178\002S\000\160\003'\002u\0034\001\214\002\138\003\007\002\134\001\184\004a\005\177\005\187\001\185\000\160\000^\004\014\000^\000k\002w\000\213\004\206\005\189\002x\000\214\001\215\004(\004b\004Y\004\021\001\216\000^\004\013\005M\001\217\002O\000_\002B\004\158\001\218\000`\000-\000/\001z\0002\004\023\000^\001\198\000\243\004Z\002w\000\227\002G\0006\002x\004\195\002H\001@\003\014\0007\001\199\003\252\003b\005\194\000m\000i\001\182\001\205\002[\003\015\004\024\0004\004\196\002J\004\031\004\199\004Y\002\164\000r\000-\0007\0006\005\179\002S\003T\003<\004\023\004Z\005\197\002L\004!\002\167\005'\003=\000-\003\\\004\"\001x\002B\005'\003\"\005\198\005\162\000\160\003'\003\193\0034\001\214\001\198\003\007\000-\001\184\004!\002G\000-\001\185\002\133\002H\001@\003\014\005*\001\199\003`\003b\0004\005L\003\203\001\215\004\127\002\134\003\015\000\228\001\216\0056\002J\004Z\001\217\001@\003\014\005Y\005\162\001\218\003\004\0013\003\227\000j\004%\002\133\003\004\003\015\002L\005\162\005\195\005\206\003=\004\212\003\\\000\246\001\182\001\205\002\134\003\"\004\023\0007\000\160\003'\005k\0034\001\214\000k\004\133\000-\005\135\004+\005u\002S\003T\003<\000\000\001\000\003\"\000\000\001@\000\160\003'\000-\0034\004\134\001\215\004\137\004Y\0007\005\192\001\216\001B\004.\004h\001\217\002\164\001\001\002B\003\007\001\218\001\184\001\002\001i\0041\001\185\001\003\003\228\001\198\0040\002\169\001\004\0044\002G\005\139\005\162\000\000\002H\001@\003\014\0040\001\199\003\135\003b\005\181\005\019\000\160\001l\004\023\001o\003\015\005\019\005\169\001@\002J\0036\000\000\005)\000\000\004\225\002u\004\141\005\201\002\142\005(\001B\000\000\004Z\000\000\000\152\002L\005\202\003:\000\169\003=\000\000\003\\\000\000\001\182\001\205\005\192\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\000\000\005\163\000-\000\000\000\000\000\000\002S\003T\003<\000\000\000\160\001l\005\165\001o\002A\000\211\000\000\000\236\002w\001\215\002u\002B\002x\002\142\001\216\000\000\000\160\004}\001\217\000\166\000\160\001\198\003\007\001\218\001\184\000\000\002G\000\000\001\185\004\195\002H\001@\003\014\000\000\001\199\004\000\003b\000\000\000\000\000\000\000\000\001\182\001\205\003\015\000\000\000\152\004\196\002J\000^\004\199\004Y\000\213\000-\002A\000-\000\214\005 \002w\005/\000\000\003\006\002x\000\000\002L\000\000\000\000\000\000\003=\005\167\003\\\000\000\000\000\000\000\000\000\003\"\004\161\000\000\000\160\003'\000\000\0034\001\214\000\227\000\000\003\007\000\000\001\184\000\000\000\000\000\000\001\185\000\160\001)\000\000\000\166\000\000\000\000\000\211\000\000\000\232\000\000\001\215\005\132\001\182\001\205\002\133\001\216\000\000\002\200\004Z\001\217\000\000\004a\002B\002\161\001\218\000-\000\000\002\134\000\000\005/\000\000\003\006\001\198\000\000\000\000\000\000\000\000\002G\004b\004Y\000\000\002H\001@\003\014\000\000\001\199\005U\003b\002\202\000^\000\000\000\000\000\213\000\000\003\015\003\007\000\214\001\184\002J\000\000\000\000\001\185\000\000\002\133\002\198\000\000\002\196\000\000\000\000\000\000\000\000\000\228\002\161\005v\002L\000\\\002\134\000\000\003=\000e\003\\\000\000\000\000\000\227\002B\003\"\000\000\000\000\000\160\003'\002\208\0034\001\214\000\000\001\198\000\000\002\164\002\199\004Z\002G\000\000\000\000\005!\002H\001@\003\014\005w\001\199\000\000\000\000\002\165\004\195\001\215\005#\005$\005=\005W\001\216\000^\000\000\005z\001\217\000\000\000_\004\233\000\000\001\218\000`\004\196\000\000\000\000\004\199\004Y\000\000\000\000\000\000\002L\000\000\000\000\000\237\003\029\005|\000\000\000\000\000\000\002\164\002B\003\"\000\160\000\000\000\160\003'\000i\0034\001\214\004\195\001\198\000\000\000\000\002\165\000\000\002G\000-\000\228\000\000\002H\001@\003\014\005w\001\199\000\000\000\000\004\196\000\186\001\215\004\199\004Y\005=\005W\001\216\004\133\000\000\005z\001\217\000\000\000\000\000\000\002u\001\218\000\000\002\142\004Z\000-\000/\0000\0002\000\000\004\134\002L\004\137\004Y\000\000\003\029\005|\001\182\001\205\000\000\004n\000\000\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\000-\000\000\000\000\000\000\005/\0004\003\006\000\000\000\000\000\000\000\211\000\000\000\231\002A\000\000\000j\000\000\002w\004Z\001\215\000\000\002x\002u\000\000\001\216\002\142\000\000\000\000\001\217\000\000\003\007\000\000\001\184\001\218\000\188\000\000\001\185\000\000\000\211\000k\000\238\004a\004Z\000\000\000-\000/\001v\0002\005y\001\182\001\205\000\000\000\000\000^\000\000\000\000\000\213\000\\\004b\004Y\000\214\000q\000-\000\000\000\138\002A\002S\005\015\003\006\002w\000\000\000\000\000\000\002x\0004\000\000\000\000\000\000\000\000\002u\004\236\000^\002\137\000\000\000\213\000m\000\152\000\227\000\214\000\139\000\000\000\000\003\007\000\140\001\184\000\000\000\000\000\000\001\185\000o\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000\000\000\000\000\000\002\133\000\227\001@\002\203\004Z\000\000\000\000\002B\000^\002\161\004\243\004\006\002w\002\134\001B\003\130\002x\001\198\000\160\001~\000i\000\166\002G\001\182\001\205\001i\002H\001@\003\014\005w\001\199\000\000\000\000\000\000\000\000\004\218\000-\000\000\005=\005W\002S\000\000\003\006\005z\000\000\000\000\000-\000\000\000\160\001l\000-\001o\002\133\000\228\005 \002\200\000\000\000\000\000\000\002L\000\000\002\161\000\000\003\029\005|\002\134\003\007\000-\001\184\002B\003\"\001@\001\185\000\160\003'\002\206\0034\001\214\000\000\001\198\002Z\000\228\002\164\001B\002G\000\000\002\202\000\000\002H\001@\003\014\000\000\001\199\000\000\001i\000\000\002\165\001\215\004a\003\128\000j\003\015\001\216\003\130\000\000\003w\001\217\005\013\000\000\002\133\000\000\001\218\000\000\004l\000\000\004b\004Y\000\160\001l\000\000\001o\002L\002\134\000\000\000k\003\029\003y\000\000\002\207\001\000\000\000\000\000\003\"\000\000\002\164\000\160\003'\000\000\0034\001\214\000\000\000\000\000\\\001\182\001\205\000\000\000e\000\000\002\165\001\001\002Q\000\000\000\000\000\000\001\002\000\000\000-\002B\001\003\001\215\002S\003\001\003\006\001\004\001\216\004a\000\000\001\198\001\217\000\000\000m\000\000\002G\001\218\000\000\004Z\002H\001@\003\014\000\000\001\199\000\000\004b\004Y\000t\000^\003\007\000\152\001\184\003\015\000_\001@\001\185\003w\000`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005#\0050\000-\000\134\000\000\000\000\000\152\002L\000\000\000\000\000\000\003\029\003y\000\000\000\000\000\000\000\000\000i\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\000\000\000\000\000\000\001\182\001\205\000\160\001\128\000\000\000\166\000\160\002\235\003\031\002\249\000\000\004Z\000\000\000-\000\000\000\000\001\215\002S\003 \003<\000\000\001\216\000\000\000\160\001\141\001\217\000\166\000\000\005E\000\000\001\218\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\182\001\252\003\007\000\000\001\184\002B\000\000\000\000\001\185\000\000\001\182\001\202\004y\004a\000\000\001\198\000\000\000\000\000\000\000\000\002G\001\182\001\205\000\000\002H\001@\003\014\000j\001\199\003?\004b\004Y\000\000\000\000\000-\000\000\000\000\003\015\002S\003 \003<\003A\000\000\000^\000\000\001\184\000\137\000\000\000\000\001\185\000\000\000k\000\000\000^\000\000\001\184\000\000\002L\000\000\001\185\004a\003\029\003C\000\000\003\007\000\000\001\184\000\000\003\"\000\000\001\185\000\160\003E\001@\0034\001\214\000\138\004b\004Y\004w\000\000\000\000\000\000\001\182\001\205\005F\000\000\000\\\000\000\000\000\004Z\000q\000\000\002B\000\000\001\215\000\000\000m\000\000\000\000\001\216\000\139\003J\001\198\001\217\000\140\000\000\000\000\002G\001\218\000\000\000o\002H\001@\003\014\000\000\001\199\005I\000\000\000\160\005J\000\000\000\166\001\182\001\205\003\015\002A\000\000\001\184\002J\000^\003D\001\185\000\000\000\000\000_\000-\004Z\000\000\000`\002S\003 \003<\000\000\001\198\002L\000\000\000\000\000\000\003=\000\000\003>\000\000\000\000\001\198\002B\003\"\001\199\000\000\000\160\003'\000\000\0034\001\214\000i\001\198\003\007\001\199\001\184\000\000\002G\000\000\001\185\000\000\002H\001@\003\014\000\000\001\199\000\000\000\000\000\000\000\000\001\215\000\000\001\182\001\205\003\015\001\216\000\000\000\000\002J\001\217\000\000\000\000\000\000\000\000\001\218\000-\004u\000\000\000\000\002S\003T\003<\000\000\000\211\002L\000\236\000\000\000\000\003=\000\000\003>\000\000\000\000\000\000\002B\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\000\000\001\198\003\007\000\000\001\184\000\000\002G\000\000\001\185\000\000\002H\000\000\000\000\000\000\001\199\000\000\000\000\000\000\000j\001\215\004\153\001\182\001\205\000^\001\216\000\000\000\213\002J\001\217\000\000\000\214\002B\000\000\001\218\000-\000\000\000\000\000\000\002S\003T\003<\001\198\000k\002L\000\000\000\000\002G\000\000\000\000\000\000\002H\001@\003\014\000\000\001\199\004a\000\000\000\227\000\000\000\000\000\000\001\214\000\000\003\015\003\007\000\000\001\184\002J\000\000\000\000\001\185\000\000\004b\004Y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\215\000\000\002L\000\000\000\000\001\216\003=\000m\003>\001\217\000\000\000\000\002B\003\"\001\218\002u\000\160\003'\002\142\0034\001\214\000v\001\198\000\000\000\\\000\000\000\000\002G\000g\000\000\000\000\002H\001@\003\014\000\000\001\199\000\000\003[\000\000\000\000\001\215\000\000\001\182\001\205\003\015\001\216\000\000\000\000\002J\001\217\000\000\004Z\000\000\000\000\001\218\000-\000\228\000\000\002A\002S\003T\003<\002w\000\000\002L\000\000\002x\000^\003=\000\211\003\\\000\230\000_\000\000\002B\003\"\000`\000\000\000\160\003'\000\000\0034\001\214\000\000\001\198\003\007\000\000\001\184\000\000\002G\000\000\001\185\000\000\002H\001@\003\014\000\000\001\199\000\000\003]\000\000\000i\001\215\000\000\001\182\001\205\003\015\001\216\000\000\000\000\002J\001\217\000^\000\000\000\000\000\213\001\218\000-\000\000\000\214\000\000\002S\003z\003<\001\001\000\000\002L\000\000\000\000\000\000\003=\000\000\003\\\000\000\000\000\000\000\000\000\003\"\001\008\000\000\000\160\003'\000\000\0034\001\214\000\000\000\227\003\007\000\000\001\184\000\000\000\000\000\000\001\185\000\000\001\182\001\201\000\000\000\000\002\133\004\165\000\000\002\200\000\000\001\215\000\000\001\182\001\205\002\161\001\216\000\\\000\000\002\134\001\217\000e\000\000\002B\000\000\001\218\000-\000\000\000j\003|\002S\003z\003<\001\198\000\000\000\000\000\000\000\000\002G\000\000\002\202\000-\002H\001@\003\014\000^\001\199\001\184\003o\000\000\004\195\001\185\000k\000\000\000\000\003\015\003\007\000\000\001\184\002J\000^\000\000\001\185\000\000\000\000\000_\000\000\004\196\000\000\000`\004\199\004Y\000\000\000\228\000\000\002L\000\000\000l\000\000\003=\001\026\003\\\002\205\000\000\000\000\002B\003\"\000\000\002\164\000\160\003'\003~\0034\001\214\000i\001\198\000\000\000\000\000m\000\000\002G\004\232\002\165\000n\002H\001@\003\014\000\000\001\199\000\000\000\000\000\000\000o\001\215\000\000\001\182\001\205\003\015\001\216\000\000\000\000\002J\001\217\003\144\000\000\000\000\000\000\001\218\000-\000\000\004Z\004\235\002S\003 \003<\000\000\000\000\002L\000\000\000\000\000\000\003=\000\000\003}\000\000\000\000\001\198\002B\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\000\000\001\198\003\007\001\199\001\184\000\000\002G\000\000\001\185\000\000\002H\001@\003\014\000\000\001\199\000\000\000\000\000\000\000j\001\215\000\000\001\182\001\205\003\015\001\216\000\000\000\152\002J\001\217\000\000\000\000\000\000\000\000\001\218\000-\000\000\000\000\000\137\002S\000\000\003\006\000\000\000k\002L\000\000\000\000\000\000\003=\000\000\003}\000\000\000\000\000\000\000\000\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\001\182\001\200\003\007\000\000\001\184\000\138\000\000\000\000\001\185\000\000\000\160\004\227\000\000\000\166\000\000\000\000\000\000\000\000\004\238\001\215\000\000\000\000\000\000\000\000\001\216\000\000\000m\000\000\001\217\002u\000\139\002B\002\142\001\218\000\140\003\250\001\182\001\205\000\000\003\130\000o\001\198\000\000\000^\000\000\001\184\002G\001\182\001\205\001\185\002H\001@\003\014\000\000\001\199\002:\004\005\004a\000\000\000\211\000-\000\238\000\000\003\015\002S\000\000\003\006\002J\000\000\000\000\000\000\000\000\000^\000\000\004b\004Y\002w\000\000\000\000\002A\002x\001\184\000\000\002L\000\000\001\185\000\000\003=\000\000\003>\003\007\000\000\001\184\002B\003\"\000\000\001\185\000\160\003'\000\000\0034\001\214\000^\001\198\000\000\000\213\000\000\000\000\002G\000\214\000\000\000\000\002H\001@\003\014\000\000\001\199\000-\0003\000\000\0002\001\215\004a\004\008\000\000\003\015\001\216\003\130\000\000\003w\001\217\000\000\000\000\000\000\004Z\001\218\000\227\000\000\000\000\004b\004Y\000\000\000\000\000\000\001\198\002L\000\000\0004\000\000\003\029\003y\000\000\000\000\000\000\000\000\000\000\003\"\001\199\000\000\000\160\003'\000\000\0034\001\214\000\000\001\182\001\205\000\000\000\000\000\000\002B\000\000\000\\\002\133\000\000\000\211\000g\000\238\000-\000\000\001\198\002B\002S\001\215\003\006\002G\002\134\000\000\001\216\002H\000\000\001\198\001\217\001\199\000\000\000\000\002G\001\218\000\000\004Z\002H\001@\003\014\000\000\001\199\000\000\002J\000\000\003\007\000\000\001\184\004a\000\000\003\015\001\185\000^\000\228\003w\000^\000\000\000_\000\213\002L\000\000\000`\000\214\000\000\000\000\004b\004Y\000\000\000\000\000\000\002L\000\000\000\000\000\000\003\029\003y\000\000\001\214\004\n\000\254\004\174\003\"\003\130\000\000\000\160\003'\000i\0034\001\214\000\227\000\000\000\000\002\143\000\000\000\000\001@\000\000\001\215\000\000\000\000\000\000\001\000\001\216\000\000\000\000\000\000\001\217\001B\001\215\000\000\000\000\001\218\000\000\001\216\000\000\001\182\001\205\001\217\001i\000\000\000\000\001\001\001\218\0058\000\000\004Z\001\002\000\000\000-\000\000\001\003\000\000\002S\003 \003<\001\004\002B\000\211\000\000\000\238\000\000\000\160\001l\000\000\001o\004\172\001\198\000\000\000\000\000\000\000\000\002G\000\000\000\000\000\000\002H\001@\003\014\003\007\001\199\001\184\000\000\000\000\000\000\001\185\000\000\000j\000\000\003\015\000\228\000\000\000\000\003w\001\182\001\183\000\000\000\000\000\000\000\000\000\000\000^\000\000\000\000\000\213\000\000\000\000\000\000\000\214\002L\000\000\000k\000\000\003\029\003y\000\000\004\016\000\000\000\000\000\000\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\000\000\000\000\000\000\000\000\001\182\001\205\000\000\000\227\000l\000^\001\000\001\184\005[\000\000\000\000\001\185\000\000\000-\000\000\001\215\000\000\002S\003 \003<\001\216\000\000\000\000\004\216\001\217\000m\001\001\000\000\000\000\001\218\000\148\001\002\000\000\000\000\000\000\001\003\001\182\001\203\002B\000o\001\004\000\000\000\000\003\007\000\000\001\184\000\000\000\000\001\198\001\185\000\000\000\000\000\000\002G\000\000\000\000\000\000\002H\001@\003\014\000\000\001\199\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\015\000\000\000\000\000\\\002J\000\000\000\000\000e\000\000\000^\000\000\001\184\000\000\000\228\000\000\001\185\000\000\000\000\000\000\000\000\002L\000\000\000\000\000-\003=\000\000\003>\003\139\001\182\001\205\000\000\003\"\000\000\000\000\000\160\003'\001\198\0034\001\214\004\018\000\000\000-\000\000\000\000\000\000\002S\000^\003<\000\000\001\199\000\000\000_\000\000\002Z\000\000\000`\000\000\000\000\001\215\000\000\000\000\001\000\000\000\001\216\002B\000\000\001\240\001\217\000\000\000\000\000\000\003\007\001\218\001\184\001\198\000\000\000\000\001\185\000\000\002G\000i\001\001\000\000\002H\001@\003\014\001\002\001\199\000\000\000\000\001\003\000\000\001\182\001\205\000\000\001\004\003\015\000\000\000-\000\000\002J\000\000\000\000\003@\000\000\000-\000\000\000\000\000\000\002S\001\198\003\006\000\000\000\000\000\000\000\211\002L\000\238\000\000\000\000\003=\000\000\003>\001\199\000\000\000\000\000\000\003\"\003\158\000\000\000\160\003'\000\000\0034\001\214\003\007\000\000\001\184\000\000\000\000\000\000\001\185\000\000\000\000\000\000\000\211\000\000\000\238\000\000\000\000\000\211\000\000\000\229\000\000\001\215\000\000\001\182\001\205\000^\001\216\000j\000\213\002B\001\217\001@\000\214\000\000\003\005\001\218\000-\001\242\000\000\001\198\002S\000\000\003\006\002\223\002G\000\000\000\137\000\000\002H\001@\003\014\000k\001\199\000\000\000\000\000^\000\000\001\215\000\213\000\227\000^\003\015\000\214\000\213\000\000\003\141\003\007\000\214\001\184\000\000\000\000\001\218\001\185\000\000\000\000\000\000\000\138\000\160\002\235\000\000\002\249\002L\000\000\000\000\000\000\003=\000\000\003\143\000\000\000\227\000\000\000\000\003\"\002B\000\227\000\160\003'\000m\0034\001\214\000\000\000\139\000\000\001\198\000\000\000\140\001@\000\000\002G\000\000\000\000\000o\002H\001@\003\014\000\000\001\199\000\000\003\164\001\215\000\000\001\182\001\205\000\000\001\216\003\015\000\000\000\000\001\217\003\027\000\000\000\000\003!\001\218\000-\000\000\000\000\000\000\002S\000\228\003\006\000\000\000\000\000\000\000\000\002L\000\000\000\000\000\000\003\029\003\030\000\000\000\160\003\176\000\000\003\182\003\"\002B\000\000\000\160\003'\000\000\0034\001\214\003\007\004\020\001\184\001\198\000\000\000\228\001\185\000\000\002G\000\000\000\228\000\000\002H\001@\003\014\000\000\001\199\000\000\000\000\001\215\000\000\001\182\001\205\001\000\001\216\003\015\000\000\000\000\001\217\003\027\000\000\004$\000\000\001\218\000-\000\000\000\000\000\000\002S\000\000\003\006\000\000\000\000\001\001\000\000\002L\000\000\000\000\001\002\003\029\003\030\000\000\001\003\001\000\000\000\000\000\003\"\001\004\000\000\000\160\003'\000\000\0034\001\214\003\007\000\000\001\184\000\000\000\000\000\000\001\185\000\000\000\000\001\001\000\211\000\000\000\236\000\000\001\002\000\211\000\000\000\212\001\003\001\215\000\000\001\182\001\205\001\004\001\216\000\000\000\000\002B\001\217\000\000\000\000\000\000\000\000\001\218\000-\000\000\000\000\001\198\002S\000\000\003\006\000\000\002G\000\000\000\000\000\000\002H\001@\003\014\000\000\001\199\000\000\000\000\000^\000\000\000\000\000\213\000\000\000^\003\015\000\214\000\213\000\000\003\027\003\007\000\214\001\184\000\000\000\000\000\000\001\185\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002L\000\000\000\000\000\000\003\029\003\030\001\182\001\205\000\227\000\000\000\000\003\"\002B\000\227\000\160\003'\000\000\0034\001\214\000-\000\000\000\000\001\198\002S\000\000\003\006\000\000\002G\000\000\000\000\000\000\002H\001@\003\014\000\000\001\199\000\000\000\000\001\215\000\000\000\000\003_\000\000\001\216\003\015\000\000\000\000\001\217\003X\003\007\000\000\001\184\001\218\000\000\000\000\001\185\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002L\000\000\000\000\000\000\003\029\003Z\001\182\001\205\000\000\000\000\002u\003\"\002B\002\136\000\160\003'\000\000\0034\001\214\000-\000\000\000\000\001\198\002S\000\228\003\006\000\000\002G\000\000\000\228\000\000\002H\001@\003\014\000\000\001\199\000\000\000\211\001\215\000\238\000\000\003W\002u\001\216\003\015\002\135\000\000\001\217\003X\003\007\000\000\001\184\001\218\000^\000\000\001\185\000\000\002w\000\000\000\000\000\000\002x\000\000\000-\002L\000\000\005\012\000\000\003\029\003Z\000-\000\000\001\028\000\000\002S\003\"\002B\000\000\000\160\003'\000^\0034\001\214\000\213\000\000\000^\001\198\000\214\000\000\002w\000\000\002G\001\001\002x\000\000\002H\001@\003\014\000\000\001\199\004(\000\000\001\215\000\000\003k\000\000\001\004\001\216\003\015\000\000\000\000\001\217\003l\000\000\000\227\000\000\001\218\001U\000\000\000\000\000\000\000\000\000-\001k\000\000\0002\000\000\000\000\002L\000\000\000\000\001O\003\029\003n\001\182\001\205\000\000\000\000\002u\003\"\002B\002v\000\160\003'\000\000\0034\001\214\000-\000\000\000\000\001\198\002S\0004\003\006\002\133\002G\000\000\000\000\000\000\002H\001@\003\014\000\000\001\199\000\000\000\000\001\215\002\134\000\000\003i\000\000\001\216\003\015\000\000\000\000\001\217\003X\003\007\000\000\001\184\001\218\000^\000\000\001\185\000\000\002w\002\133\000\000\000\000\002x\000\000\000\000\002L\000\000\000\228\000\000\003\029\003Z\000\000\002\134\000\000\000\000\000\000\003\"\001@\000\000\000\160\003'\000\000\0034\001\214\001@\003\014\000\000\003v\000\000\001P\000\000\000\000\000\000\005\013\001\182\001\205\003\015\000\000\000\000\000\000\000\000\000\000\000\000\001\215\000\000\000\000\000\000\000-\001\216\001\182\001\203\002S\001\217\003\006\000\000\001\000\001[\001\218\001f\000\000\004-\001X\000\000\000\160\001Y\005\016\000\166\003\"\000\000\000\000\000\160\003'\000\000\0034\000\000\001\001\001@\003\007\000\000\001\184\001\002\002B\000\000\001\185\001\003\000\000\000\000\000\000\001B\001\004\000\000\001\198\000^\000\000\001\184\002\133\002G\000\000\001\185\001i\002H\001@\003\014\000\000\001\199\000\000\000\000\000\000\002\134\000\000\000\000\001\182\001\205\003\015\003{\000\000\000\000\003w\000\000\000\000\000\000\0054\000\160\001l\000-\001o\000\000\000\000\002S\000\000\003\006\000\000\000\000\002L\000\000\000\000\000\000\003\029\003y\000\000\000\000\000\000\000\000\000\000\003\"\000\000\000\000\000\160\003'\000\000\0034\001\214\000\000\000\000\003\007\000\000\001\184\000\000\000\000\000\000\001\185\000\000\001\182\001\205\000\000\000\000\000\000\000\000\002B\000\000\000\\\001\215\000\000\000\000\000e\000-\001\216\000\000\001\198\003\157\001\217\000\000\000\000\002G\000\000\001\218\000\000\002H\001@\003\014\000\000\001\199\000\000\001\198\000\000\000\000\000\000\000\000\003\189\000\000\003\015\001\182\001\203\000\000\003w\003\192\001\199\001\184\000\000\000\000\000\000\001\185\000\000\000^\000\000\000\000\000\000\000\000\000_\000\000\002L\000\000\000`\000\000\003\029\003y\001\182\001\205\003\198\000\000\000\000\003\"\000\000\002\031\000\160\003'\000\\\0034\001\214\000-\000q\000\000\000\000\003\157\000^\002B\001\184\000i\000\000\000\000\001\185\000\000\000\000\000\000\000\000\001\198\003\236\000\000\001\215\001\210\002G\001%\003\240\001\216\002H\001@\003\014\001\217\001\199\003\192\000\000\001\184\001\218\001\215\000\000\001\185\000\000\003\015\000\000\000^\000\000\0055\000\000\000\000\000_\000\000\000\000\001\220\000`\000\000\000\000\000\\\003\198\000\000\000\000\000g\000\000\002L\000\000\000\000\000\000\003\029\0057\000\000\000\000\000\000\001\198\000\000\003\"\000\000\000\000\000\160\003'\000i\0034\001\214\001@\003\199\000\000\001\199\000\000\000\000\000\000\000\000\001\182\001\205\000\000\000j\003\200\000\000\000\000\000\000\003\238\000\000\000^\001\215\000\000\000-\000\000\000_\001\216\003\157\000\000\000`\001\217\001\198\000\137\000\000\000\000\001\218\000\000\000k\000\000\000\000\000\000\000\000\000\000\000\000\001\199\003\214\003\191\000\000\000\160\003\239\000\000\003\226\001\214\003\192\000i\001\184\001\198\000\000\000\211\001\185\000\236\000\000\000\138\000\000\000\000\000\000\001@\003\199\000\000\001\199\000\000\000\\\001\215\000\000\000\000\000e\003\198\001\216\003\200\000j\000\000\001\217\003\212\000m\000-\000\000\001\218\000\139\000\000\000\000\000\000\000\140\000\000\000\000\000\211\000\000\000\236\000o\000\000\000\000\000\000\000^\000\000\000k\000\213\000\000\000\000\000\000\000\214\003\214\000\000\001\215\000\160\003\219\000^\003\226\001\214\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\001\222\000\000\000\000\000\136\000\000\000\000\000\000\000\000\000\000\000j\000\227\001\215\000^\000\000\000\000\000\213\001\216\000\\\000\000\000\214\001\217\000e\000\000\000i\000m\001\218\000\000\000\000\000\\\001\198\000-\000\000\000e\000k\000\000\000\000\000\000\000\000\000o\001@\003\199\000-\001\199\000\000\000\000\000\000\000\227\000\000\000\000\000\000\000\000\003\200\000\000\000\000\000\000\003\212\000\000\000\000\000l\000\000\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000m\000`\000\000\003\214\000\000\000\151\000\160\003\219\000\000\003\226\001\214\000\228\000\000\000\000\000o\000i\000\000\000\000\000\000\000\000\000\000\000\152\000\000\000\000\000j\000\000\000i\000\000\000\000\000\000\001\215\002u\000\\\000\000\002\142\001\216\000e\000\000\000\000\001\217\000\155\000\156\000\158\000\159\001\218\000-\000\000\000\228\000k\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\160\000\165\000\000\000\166\000\000\000\000\000\138\000^\000^\000\000\000\000\002w\001\001\000_\000\000\002x\000\000\000`\000\\\000\000\000\000\000\000\000q\000\000\000\000\000\152\001\n\000m\000j\000\000\000\000\000\139\000\000\000-\000\000\000\140\000\152\000\000\000\000\000j\000\000\000o\000i\000\171\000\155\000\218\000\158\000\159\001\001\000\000\000\000\000\000\000k\000\000\000\000\000\155\001\189\000\158\000\159\000\000\000\000\000^\001\012\000k\000\000\000\000\000_\000\000\000\000\000\000\000`\000\160\000\165\000\000\000\166\000\000\000\000\000\138\000\000\000\000\000\000\000\000\000\160\000\165\000\000\000\166\000\000\001U\000\138\000\000\000\000\000\000\000\000\000\000\000\000\000i\000\000\000\000\000m\000\000\000\000\001O\000\139\000\000\000\000\000\000\000\140\000\\\002\133\000m\000\000\000e\000o\000\139\000\171\000\000\000\000\000\140\000\000\000\152\000-\002\134\000j\000o\000\000\000\171\000\000\000\000\000\000\000\000\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\155\002D\000\158\000\159\000\000\000-\000\000\000\\\000k\000\000\000\000\000q\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000\000\000\000\000\000\000\000\000\160\000\165\000\000\000\166\000\000\000\000\000\138\000\000\000^\001@\000j\000\000\000\000\000_\000\000\000\000\000\000\000`\000\211\000i\000\238\001P\000\000\000^\000\000\002\164\000\000\000m\000_\000\000\000\000\000\139\000`\000\000\000k\000\140\000\\\000\000\000\000\002\171\000e\000o\000i\000\171\000\000\000\000\000\000\000\000\001[\000-\001\\\000\000\000\000\001X\000\000\000\160\001Y\000i\000\166\000\\\000\000\000^\000\000\000e\000\213\000\000\000\000\000\000\000\214\000\000\000\000\000\000\000-\000\000\000\000\000\000\000\000\000\000\000\000\000^\000m\000\000\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000\000\000\000\000\000\000\000\000x\000\227\000\152\000\000\000\000\000j\000\000\000\\\000^\000\000\000\000\000g\000\000\000_\000\000\000\000\000\000\000`\000\000\000i\000\000\000\155\002|\000\158\000\159\000\152\000\000\000\000\000j\000k\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000i\000j\000\155\003$\000\158\000\159\000\160\000\165\000^\000\166\000k\000\000\000\138\000_\000\000\000\\\000\000\000`\000\000\000e\000\000\001#\001%\000\000\000\000\000k\000\000\000\000\000-\000\160\000\165\000\000\000\166\000m\000\000\000\138\000\000\000\139\000\000\000\228\000-\000\140\000i\000\000\000\000\000\000\000\000\000o\000\000\000\171\000\000\000\000\000\000\000\000\000\152\000\000\000m\000j\000^\000\000\000\139\000\000\000\000\000_\000\140\0043\000\000\000`\000\000\000\000\000o\000m\000\171\000\155\003\216\000\158\000\159\000\152\000\000\000\000\000j\000k\000\000\000\000\000\000\000z\000\000\001\000\000\000\000\000\000\000\000\000\000i\000\000\001U\000\000\000\000\000\000\000\000\000\188\000\160\000\165\000\000\000\166\000k\000\000\000\138\001\001\001O\000\000\000\000\000\000\001\002\000\000\000\000\000\000\001\003\001\182\001\205\000-\000\000\001\004\000j\000\160\001'\000\000\000\166\000m\000\000\000\138\000\000\000\139\000\000\000\000\000\\\000\140\003H\000\000\000e\000\000\000\000\000o\000\000\000\171\000\000\000\000\000k\000-\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\000\000\000\000\\\000\140\000\000\002A\000e\001\184\000\000\000o\000\000\001\185\000\000\000\000\000\152\000-\000l\000j\001U\000\000\000\000\000\000\000^\000\000\000\000\000\000\001@\000_\000\000\000\000\000\000\000`\001O\000\173\000\000\000\000\000\159\000m\001P\000\000\000\000\000k\000\240\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\000o\000\000\000\000\000`\003N\000i\000\000\000\000\001\210\000\160\000\165\000\000\000\166\000\\\001[\000\138\001a\000e\000\000\001X\000\000\000\160\001Y\000\000\000\166\000\000\000-\000\000\000i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\000\000\000\000\000\000\140\002B\000\000\000\000\000\000\000\000\000o\000\000\000\171\000\000\001@\001\198\000^\000\000\000\000\000\000\002G\000_\000\000\000\000\002H\000`\001P\000\000\001\199\000\000\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\000\000\000\000\000\003P\000\152\000-\000\000\000j\000\000\000\000\000\000\000\000\000i\000\000\000\000\001[\000\000\001\137\000\000\002L\001X\000\000\000\160\001Y\000\000\000\166\000\183\000\152\000\000\000\000\000j\000k\000\\\000\000\000\000\000^\000g\001\214\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000\000\000\000\000\000\000\195\000\160\001-\000\000\000\166\000k\000\\\000\138\001\215\000\000\000e\000\000\000\000\001\216\000\000\000\000\000\000\001\217\000\000\000-\000i\000\000\001\218\000\000\000\160\000\197\000^\000\166\000m\000\000\000\138\000_\000\139\000\000\000\000\000`\000\140\000\000\000\000\000\000\000\152\000\000\000o\000j\000\000\000\000\000\000\000\000\000\000\000^\000\000\000m\000\000\000\000\000_\000\139\000\000\000\000\000`\000\140\000i\000\000\000\195\000\000\000\\\000o\000\000\000k\000e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000-\000\000\000\000\000\000\000\000\000\000\000i\000\000\000\000\000\160\000\234\000\000\000\166\000\000\000\000\000\138\000\000\000\000\000\000\000\000\000\152\000\000\000\000\000j\000\000\000\000\000\000\000\000\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\000m\000\000\000\000\000`\000\139\000\000\000\183\000\000\000\140\000\000\000\000\000k\000\000\000\000\000o\001\182\001\205\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000j\000i\000\000\000\160\0016\000\000\000\166\002:\003Q\000\138\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\000\000\000\000\152\000\000\000\000\000j\000k\000\000\000\000\000\000\000\000\000\000\000m\002A\000\000\001\184\000\139\000\000\000\000\001\185\000\140\000\000\000\000\000\000\001\165\000\000\000o\001\182\001\205\000k\000\000\000l\000\000\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\002:\003G\000\160\001\167\000\000\000\166\000m\000\000\000\138\002!\000\000\000\242\000\000\000\000\000\152\000\000\000\000\000j\000\000\000\000\000o\000\000\000\000\000i\002A\000\000\001\184\001\182\001\205\000m\001\185\000\000\000\000\000\139\000\000\000\000\001\165\000\140\000\000\001\182\001\203\000k\000\000\000o\000\000\000\000\002:\002;\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\182\001\205\000\000\002B\000\000\000\160\001\250\000\000\000\166\000\000\000\000\000\138\000\000\001\198\000\000\002A\000\000\001\184\002G\002:\002F\001\185\002H\000\000\000\000\000\000\001\199\000^\000\000\001\184\000\000\000\000\000m\001\185\000\000\000\000\000\139\000\000\000\\\002J\000\140\000\000\000e\002A\000\000\001\184\000o\000\000\000j\001\185\000\000\000\000\000\000\000\000\000\000\002L\000\000\000\000\000\000\000\000\002B\000\\\000\000\000\000\000\000\000e\000\000\000\137\000\000\000\000\001\198\000\000\000k\001\214\000-\002G\000\000\000\000\000\000\002H\000\000\000^\000\000\001\199\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000\000\001\215\000\000\000\000\002J\000\138\001\216\000\000\000\000\002#\001\217\000\000\000^\000\000\002B\001\218\000\000\000_\000\000\000\000\002L\000`\000\000\000i\001\198\000\211\000m\000\236\000\000\002G\000\139\000\\\000\000\002H\000\140\000e\001\198\001\199\001\214\000\000\000o\000\000\002B\000\000\000-\000\000\000i\000\000\000\000\001\199\002J\000\000\001\198\000\000\000\000\000\000\000\000\002G\001\215\000\000\000\000\002H\000\000\001\216\000\000\001\199\002L\001\217\000^\000\000\000\000\000\213\001\218\000\000\000^\000\214\001\182\001\203\002J\000_\000\000\000\000\000\000\000`\001\214\000\000\000\000\000\000\000\000\000\000\000\000\001\182\001\205\000\000\002L\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\227\000j\001\215\000\000\000\000\000\000\000i\001\216\002:\003S\001\214\001\217\000\000\000\000\001\215\000\000\001\218\000^\000\000\001\184\000\137\000\152\000\000\001\185\000j\000k\000\000\000\000\001\224\000\000\001\215\000\000\002A\000\000\001\184\001\216\000\000\000\000\001\185\001\217\000\000\000\000\000\000\002e\001\218\000\000\001\182\001\205\000k\000\000\000\138\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\182\001\205\000\000\000\000\000\000\000\000\000\000\002:\004\026\000\160\002g\000\000\000\166\000m\000\000\000\138\000\000\000\139\000\000\002:\004\028\000\140\000\228\000\000\000\000\000\152\000\000\000o\000j\000\000\000\000\002A\000\000\001\184\000\000\000\000\000m\001\185\000\000\000\000\000\139\000\000\000\000\002A\000\140\001\184\000\211\002e\000\236\001\185\000o\000\000\000k\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\198\000\000\001\182\001\205\000\000\002B\000\\\000\000\000\000\000\000\000e\000\160\002\140\001\199\000\166\001\198\000\000\000\138\000\000\000\000\002G\002:\004\030\000\000\002H\000\000\000\000\000\000\001\199\000^\001\001\000\000\000\213\000\000\000\000\000\000\000\214\000\000\000m\000\\\000\000\002J\000\139\000e\001\014\002A\000\140\001\184\000\000\000^\000\000\001\185\000o\000\000\000_\000\000\000\000\002L\000`\000\000\000\000\000\000\002B\000\227\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\198\000\000\002B\001\214\000\000\002G\000\000\000\000\001\215\002H\000^\000i\001\198\001\199\000\000\000_\000\000\002G\000\000\000`\000\000\002H\001\226\001\215\000\000\001\199\002J\000\000\001\216\000\000\000\000\000\000\001\217\000\000\000\000\000\000\000\000\001\218\002J\000\000\000\000\000\000\002L\000\000\000i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002L\000\\\000\000\000\000\000\000\000e\001\214\000\000\000\000\000-\002B\002b\000\000\000\000\000\000\000\000\000\000\000\228\001\214\000\000\001\198\000\000\000\000\000\000\000\000\002G\001\215\000\000\002\216\002H\000\000\001\216\000\000\001\199\000\000\001\217\002u\000j\001\215\002\142\001\218\000\000\000\000\001\216\000^\000\000\002J\001\217\000\000\000_\000\000\000\000\001\218\000`\000\\\000\000\002\156\000\000\000e\000\000\000\000\000k\002L\001U\000\000\000\\\000\000\000\000\000\000\000e\000j\000\000\000\000\000\000\000\000\000\000\000\000\001O\000i\000^\001\214\000\000\000\000\002w\000\000\001\001\000\138\002x\000\000\000\188\000\000\000\\\000\000\000\000\000k\000e\000\000\000^\000\000\001\016\001\215\000\000\000_\000\000\000\000\001\216\000`\000m\000^\001\217\000\000\000\139\000\000\000_\001\218\000\140\000\000\000`\000\\\000\138\000\000\000o\000e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000i\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\000m\000\000\000i\000`\000\139\000\000\000\000\000\000\000\140\002\154\001@\000\000\000\000\000\000\000o\000\000\000\000\000\000\000j\000\000\000\\\000^\001P\000\000\000e\000\000\000_\000\000\000i\000\000\000`\000\000\000\000\000\000\000\000\000\000\000\000\002\156\000\000\000\000\002\133\000\000\000k\000\000\000\000\000\000\000\\\000\000\000\000\001[\000e\002W\000\000\002\134\001X\000i\000\160\001Y\000\000\000\166\000\000\000\000\002\233\000^\000\000\000\000\000\000\000\138\000_\000\000\000\000\000j\000`\002\245\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000j\000\000\000\000\000\000\000\000\000\000\000m\000^\002\156\000\000\000\139\000\000\000_\000k\000\140\000i\000`\002\253\000\000\002\156\000o\000\000\000\000\000\000\000k\000\000\000j\000\000\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\000\000\000\000\138\000\\\002\164\000i\000\000\000e\003\n\002\156\000\000\000\000\000\000\000\138\000k\000\000\000\000\000j\002\173\000\000\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\000\000\\\000\000\000\140\000\000\000e\000m\000^\002\156\000o\000\139\000\138\000_\000k\000\140\000\000\000`\000\\\000^\000\000\000o\000e\003\025\000_\000\000\000\000\000\000\000`\000\000\000\000\000\000\000j\000m\000\000\000\000\000\000\000\139\000\000\000\138\000\\\000\140\000i\000\000\000e\000^\000\000\000o\000\000\0030\000_\002\156\000\000\000i\000`\000\000\000k\000\000\000j\000\000\000m\000^\000\000\000\000\000\139\000\000\000_\000\000\000\140\000\000\000`\000\\\000\000\000\000\000o\000e\000\000\002\156\000\000\000i\000\000\000\138\000k\000^\000\000\000\000\000\000\000\\\000_\000\000\000\000\000e\000`\000\000\000\000\000i\000\000\000\000\000\000\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\138\000\000\000\000\000\140\000\000\000\000\0038\000^\000\000\000o\000i\000\000\000_\000\000\000\000\000j\000`\003\162\000\000\000\000\000\000\000m\000\000\000^\000\000\000\139\000j\000\000\000_\000\140\000\000\000\000\000`\000\000\002\156\000o\000\\\000\000\000\000\000k\000e\000i\000\000\003\174\000\000\002\156\000\000\000\000\000\000\000\000\000k\000\000\000j\000\000\000\000\000\000\000\000\000i\000\000\003\180\000\000\000\000\000\000\000\000\000\138\000\000\000\000\000\000\000j\000\000\000\000\002\156\000\000\000\000\000\000\000\138\000k\000\000\000\000\000^\000\000\003\187\000\000\000\000\000_\000m\000\000\002\156\000`\000\139\000j\000\000\000k\000\140\000\000\000\000\000m\000\000\000\000\000o\000\139\000\138\000\000\000\000\000\140\000\211\000\000\000\236\000\000\002\156\000o\000\\\003\196\000i\000k\000e\000\000\000\138\000\000\000\000\000\000\000j\000m\000\\\000\000\000\000\000\139\000e\003\210\000\000\000\140\000\000\000\000\000-\000\000\005\007\000o\000j\000m\000\138\002\156\000\000\000\139\000\000\000\000\000k\000\140\000\000\000^\000\000\000\000\000\213\000o\000\000\000^\000\214\002\156\000\000\000\000\000_\000m\000k\000\000\000`\000\139\000\000\000^\000\000\000\140\000\000\000\138\000_\000\000\000\000\000o\000`\000\000\000\000\000\000\000\\\000\000\000\000\000\227\000e\003\224\000\000\000\138\001U\000i\000\000\000\000\000m\000\\\000j\000\000\000\139\000e\000\000\000\000\000\140\000i\001O\000\000\000\000\005j\000o\000\000\000m\000\000\000\000\000\000\000\139\002\156\000\000\000\000\000\140\000\000\000k\000\000\000\000\000\000\000o\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000\000\000`\000\211\000\000\000\236\000^\001\182\001\203\000\000\000\000\000_\000\000\000\138\000\000\000`\000\\\000\000\000\000\000\\\000e\000\000\000\000\000e\000\000\000\000\000\000\000i\000\000\000\000\003\231\000\\\000\000\000\228\000m\000e\000\000\000\000\000\139\000j\000i\000\000\000\140\000\000\000\000\001@\000^\000\000\000o\000\213\000^\000j\001\184\000\214\000\000\000\000\001\185\001P\002\156\000^\000\000\000\000\000^\000k\000_\000\000\000\000\000_\000`\000\000\005\020\000`\000\000\000\000\000^\000k\000\000\000\000\000\000\000_\000\227\000\000\000\000\000`\001[\000\000\002\229\000\000\000\138\001X\000\000\000\160\001Y\000i\000\166\000\\\000i\000\000\000\\\000e\000\138\001\001\000e\000\000\000\000\000\000\000\000\000j\000i\000m\000\\\000\000\000\000\000\139\000e\001\018\000\000\000\140\000\000\000\000\000j\000m\000\000\000o\000\000\000\139\0010\000\000\000\000\000\140\000\000\000k\000\000\000\000\000\000\000o\000\000\000\000\000^\005\020\000\000\000^\000\000\000_\000k\000\000\000_\000`\000\000\000\000\000`\001\198\000\000\000^\000\000\000\000\000\138\000\000\000_\000\000\000\228\000\000\000`\000\000\001\199\000\000\000\000\000\\\000\000\000\138\000\000\000e\000i\000j\000\000\000i\000j\000m\000\000\000\000\000\000\000\139\000\000\000\000\000\000\000\140\000\000\000i\000j\000\000\000m\000o\000\175\000\000\000\139\000\190\000\000\000k\000\140\000\000\000k\000\000\000\000\000\000\000o\000\000\000\000\000\221\000\000\000\000\000^\000\000\000k\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000\000\000\138\000\000\000\000\000\138\000\000\000\000\001\001\000\000\000\\\001\215\000\000\000\000\000e\000\000\000\000\000\138\000\211\000\000\000\236\000\000\001\020\000m\000i\001\228\000m\000\139\000\000\000\000\000\139\000\140\000j\000\000\000\140\000j\000\000\000o\000m\000\000\000o\000\000\000\139\000\000\000\000\000\000\000\140\000j\000\000\000\000\000\000\000\250\000o\000^\001\152\000\000\000k\000\000\000_\000k\000\000\000^\000`\000\000\000\213\000\000\001\156\000\000\000\214\000\000\000\000\000k\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\000\000\138\000\000\000\000\000\138\000\000\000\000\000i\000\000\000\\\000\000\000\000\000\000\000e\000\000\000\227\000\138\000\000\000\000\000\000\000\000\000\000\000m\000\000\000j\000m\000\139\000\000\000\000\000\139\000\140\002u\000\000\000\140\002\142\000^\000o\000m\000\000\000o\000_\000\139\000\000\001\192\000`\000\140\000\000\000\000\000k\000\\\000\000\000o\000^\000e\000\000\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000\000\000\000\000\000\000\000\000\\\000\000\000i\000\000\000e\000\000\000\138\002A\000\000\000\000\000\000\002w\000\000\000\000\000\000\002x\000\000\000\000\000\\\000i\000j\002u\000e\000\000\002\142\000^\000\000\000m\000\228\000\000\000_\000\139\000\000\000\000\000`\000\140\000\000\000\000\000\000\001\255\000\000\000o\000\000\000^\000k\000\\\000\000\000\000\000_\000e\000\000\000\000\000`\000\000\000\000\000\000\000\000\000\000\000\000\000i\000\000\000^\000\000\000\000\000^\000\000\000_\000\000\002w\000\138\000`\000\000\002x\000\000\000\000\000\000\000\\\000i\000\000\000\000\000e\000\000\000j\000\000\000\000\000\000\002u\000\000\000^\002\142\000m\000\000\000\000\000_\000\139\000i\001\001\000`\000\140\000j\000\000\002\023\000\000\000\\\000o\000\000\000k\000g\002\133\000\000\001\022\002\160\000\000\000\000\000\000\000\000\000\\\002\161\002>\000^\000g\002\134\000i\000k\000_\000\000\000\000\000\000\000`\000^\000\000\000\138\000\000\002w\000\000\000\000\000\000\002x\000\000\000j\000\000\000\000\000\000\000\000\000\000\000\000\000^\000\000\000\138\000\000\000\000\000_\000m\000i\000\000\000`\000\139\000j\002\127\000^\000\140\000\000\000\000\000k\000_\002\133\000o\000\000\000`\000m\000\000\002u\000\000\000\139\002\142\000j\002\145\000\140\002\134\000\000\000i\000k\000\000\000o\000\000\000\000\000\000\000\000\000\138\002u\002\164\000\000\002\142\000i\002\147\000\000\000-\000\000\000\000\000k\000-\000\000\000j\000\000\002\165\000\000\000\138\000\000\000\000\000m\000\000\000-\000\000\000\139\002A\000\000\000\000\000\140\002w\000\000\000-\003\150\002x\000o\000\138\000\000\000k\000m\000\000\000\000\002\133\000\139\002A\000j\000\000\000\140\002w\000\000\000\000\000\000\002x\000o\000\000\002\134\000\000\000m\000\000\002\164\000\000\000\139\001U\000\138\003\254\000\140\001U\000\000\000\000\000k\000\000\000o\000j\002\175\000\000\000\000\001O\001U\000\000\000\000\001O\000\000\000\000\000-\000m\000j\001U\000\000\000\139\000\000\000\000\001O\000\140\000\000\000\138\000\000\000k\000\000\000o\000\000\001O\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000k\000\000\000\000\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\000\000l\000\000\000\140\002\164\000\000\000\000\002\133\000\000\000o\002\163\000\000\000\000\000\000\000l\000\000\002\161\001U\002\177\000\\\002\134\000\000\000m\000q\000\000\002\133\000\000\001\207\002\212\001@\000\000\001O\000\000\001@\002\161\000m\000o\000\000\002\134\000\000\001\209\001P\000\000\000\000\001@\001P\000\000\000\000\000\000\000o\000\000\000\000\000\000\001@\000\000\000\000\001P\000\000\000\000\000\000\000\000\000\000\000^\000\000\000\000\001P\000\000\000_\001[\000\000\002\240\000`\001[\001X\003\021\000\160\001Y\001X\000\166\000\160\001Y\000\000\000\166\001[\000\000\003+\000\000\000\000\001X\002\164\000\160\001Y\001[\000\166\003\170\000\000\000i\001X\000\000\000\160\001Y\000\000\000\166\002\165\001@\000\000\000\\\002\164\000\000\000\\\000q\000\000\000\000\000q\000\000\000\000\001P\000\000\000\000\000\\\000\000\002\165\000\\\000q\000\000\000\\\000q\000\000\000\000\000q\000\000\000\000\000\\\000\000\000\000\000\000\000q\000\000\000\000\000\000\000\000\000\000\000\\\001[\000\000\003\206\000q\000\000\001X\000^\000\160\001Y\000^\000\166\000_\000\000\000\000\000_\000`\000\000\000\000\000`\000^\000\000\000\211\000^\000\236\000_\000^\000\000\000_\000`\000\000\000_\000`\000^\000j\000`\001\182\001\203\000_\000\000\000\000\000i\000`\000^\000i\000\211\000\000\000\236\000_\000\000\000\000\000\000\000`\000\000\000i\000\000\000\000\000i\000k\000\000\000i\000\000\000\211\000\000\000\236\000^\000\000\000i\000\213\000\000\000\000\000\000\000\214\000\211\000\000\000\236\000\000\000i\000\000\000^\000\000\001\184\001\182\001\203\000\000\001\185\000\000\000\000\000^\000\000\000\000\000\213\000\000\001\182\001\203\000\214\000\000\000\000\000\000\000\227\000\000\000\000\000\000\000\000\000m\000^\000\000\000\000\000\213\000\000\001\182\001\203\000\214\000\000\000\000\000\000\000^\000\000\000|\000\213\000\000\000j\000\227\000\214\000j\000^\000\000\001\184\000\000\001\182\001\203\001\185\000\000\000\000\000j\000\000\000^\000j\001\184\000\227\000j\000\000\001\185\000\000\000\000\000k\000\000\000j\000k\000\000\000\227\000\000\000\000\000^\000\000\001\184\000\000\000j\000k\001\185\000\000\000k\000\000\000\000\000k\000\000\001\182\001\203\000\000\000\000\000\000\000k\000^\000\000\001\184\000\000\000\000\000\000\001\185\000\228\001\198\000k\002u\000\000\000\000\002\142\000\000\000\000\000\000\001\182\001\203\000m\000\000\001\199\000m\000\000\000\000\001\182\001\203\000\000\000\000\000\000\000\228\000\000\000m\000~\000\000\000m\000\128\000^\000m\001\184\000\000\000\000\000\000\001\185\000\000\000m\000\130\000\228\000\000\000\132\000\000\000\000\000\142\000^\001\198\000m\000\000\002w\000\228\000\144\000^\002x\001\184\000\000\000\000\001\198\001\185\001\199\000^\000\146\001\184\000\000\000\000\002u\001\185\001\001\002\142\000\000\001\199\000\000\002u\000\000\001\198\002\142\000\000\000\000\000\000\000\000\001\215\001\024\002u\000\000\000\000\002\142\000\000\001\199\002u\000\000\001\001\002\142\000\000\001\198\001\230\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\030\000\000\001\199\001\001\000^\000\000\000\000\000\000\002w\000\000\000\000\000^\002x\000\000\001\001\002w\000\000\001 \000\000\002x\002u\000^\001\215\002\142\000\000\002w\001\198\000^\001\"\002x\000\000\002w\000\000\001\215\000\000\002x\001\232\000\000\002u\001\199\000\000\002\142\002\133\000\000\000\000\000\000\000\000\001\234\000\000\001\198\001\215\000\000\000\000\000\000\000\000\002\134\000\000\001\198\000\000\000\000\000\000\000\000\001\199\000^\001\236\000\000\000\000\002w\000\000\001\215\001\199\002x\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000^\000\000\001\238\000\000\002w\000\000\000\000\000\000\002x\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\133\001\215\000\000\000\000\000\000\000\000\000\000\002\133\000\000\000\000\000\000\000\000\000\000\002\134\000\000\001\244\000\000\002\133\000\000\002\164\002\134\000\000\000\000\002\133\001\215\000\000\000\000\000\000\000\000\000\000\002\134\000\000\001\215\002\179\000\000\000\000\002\134\000\000\001\246\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\248\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\134\000\000\000\000\000\000\000\000\002\133\000\000\000\000\000\000\000\000\002\164\000\000\000\000\000\000\000\000\000\000\000\000\002\164\002\134\000\000\000\000\000\000\000\000\000\000\002\181\000\000\000\000\002\164\000\000\000\000\000\000\002\183\000\000\002\164\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\185\000\000\000\000\000\000\000\000\000\000\002\187\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\164\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\189\000\000\000\000\000\000\002\164\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\191"))
+ ((16, "\000\209\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\249\000\000\001/\008\000\000\000\000g\000a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\188\000\000\002J\000g\000a\000\000\000\000\000\000\000\000\000\000\000\000\001t\000$\006B\000\000\000\000\000\000\t\216\000\000\000\017\000\000\000\000\001\027\002\208\000\000\000\000\000\029\000\000\000\184\000\0001\020\004p\018\252$`\000\188\000\000\000\012\000\000\000\150\t\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003`\018\252\000\000\000\000\017t\000\000\019n\000\000\0210\000\000\000\000\000\000\000\000\000\202\000\000\031\238\000\000\000\000\020\222\000\000\027\232\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018$\000\000\000\000\022\232\000\0006v\000\0007\008\000\0007>\000\0007V\000\0007|\000\0007\158\000\0007\252\000\0008\026\000\000)\178\000\000)\180\000\000\000\000\000\000\000\000\000\0008\030\000\00088\000\0008\\\000\000$\228\000\000\000\0005\176\000\000\000I\000a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\184\000\194\000\000\001\162\000\000\000\000$v\000\0001f\000\000\000\000\000\000\0010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000k2\008\000\000\001N\000\000\000\000%8\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003,%8\000\000\004\172\000\000\n\196\021\178\000\000\000\000\000\000\001\152\000\000 |\000\000\000\0002 \000\000\000\000\000\000\001\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000%R\000\000\000\130\000\000\000\000\000\0005\208\000\00060\000\000\000\000\000\000\000\000\000;\000\000\000\0002\136\000\000\000\000\000\000\nx\0018\000\000\000\000\000\000\000\000\000\000\000\000\000&\000\000\012\018\000\000\",\000\000%.\000\000'r\000\000*\000\000\000,v\000\0003,\000\0003\174\000\0007\234\000\000+^\000\000\0166\000\0007\250\000\0008\n\000\0008~\000\000\000\000\000\000\000\000\000\000\000K\t*\000\000\003\028\000\000\000\000\000\000\014\244\000\000\000\000\000\000\013\138\000\000\000\000%\232\000\000\000\000\000\000\000\000\000\000\000\000\000\191\000\000\000\000\000\000\001\206\000\000\000\000\000\000\001\014\000\000\000\000\005|\000g\000\000\000\000\000\240\002\206\000\000\000\000\000\000\000\000\000\000\002\238\000\000\005\226\000\000\001\134\000\000\000\000\003\136\000\000\000\000\000\000\000\000\000\000\000\000\007\238\000\000\000\000\000\000\002\238\000\000\000\000\000\000\000\000\019\184(H\000\000\001F\000\000\000\000\004\192\004\136\000\000\000\000\000\000\000\000\012t\000\000\000\000\000\000\000\000\000\000\000\000\001\007\012\138\000\000\014\240\000\000\000\000\000\000\000\169\000\000\012\152\000g\000\000\023\190\000\000\000\000\000\000\017x\001\214\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\158\000\000&\220\000\0002\182\000\000\000\000\000\194\000\000\006\246\000\000\006\028\018\234&\170\000\000\000\000\000\000\018\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nR&\170\000\000\023\180\000\000%\000*\160\000\000\000\000\000\000\003\242\000\000!\020\000\000\000\0003\030\000\000\000\000\000\000\005<\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0006J\000\0006N\000\000\000\000\000\000\003f\000\000\000\000\000\000\000\000\000\000\000\000\012\030\000\000\020\024\000\000 \128\000\000!\206\000\000$4\000\000'\194\000\0008L\000\0008\138\000\0008\204\000\0008\240\000\000+\180\000\000\002\220\000\0009\000\000\0009\020\000\0009>\000\000'H\000\000\000\000\000\0003@\000\000\000\000\000\000\003\216\000\0003`\000\000\000\000\000\0003\222\000\000\000\000\000\031\000\000\023p\000x\003\254\000\000\004\248\000\000\013\026\001\192\007\194\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0004>\000\000'\148% \005\186\000\000\000\000\000\000+\252\000\000,\028\000\000,>\000\000(\004(n\000w\002,\006*\000\000\000\000\000\000\003$\000\000\000\000\002(\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0004\\\000\000\000\000\000\000\000\000\000\000!\240\000\000)\000\000\000\000\000\000\000\000\000\000\000\000\000\013\220\000\000\005r\000\000\000\000\000\000\000\000\004N\001l\000\000\029\188\000\000\000\000\000\000\007d\000\000\000\000\030j\007\140\000\000\002& ~\000\000\000\000)2\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012b)2\000\000\016\202\000\000\020\178\026\148\000\000\000\000\000\000\006d\000\000\"~\000\000\000\0004\144\000\000\000\000\000\000\006\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)\174\000\000\028\224\000\000\000\0004\178\000\00052\000\000\000\000\013V\tB\000\000\000\000!\204\000\000\000\000\000\000\006\204\000\000\014\204\000\000\000\000\028\178\000\000\000\000\000\000\008<\000\000\nt\000\000\014\136\000\000\018\216\000\000\021\002\000\000\021$\000\000\026 \000\000\0306\000\000 Z\000\000#\244\000\000$\130\000\000-j\000\000-\144\000\000\000\000\000\000\000\000\000\000\000\000\003^\000\000\011\130\000\000\022\162\003\238\000\000\"8\000\000\000\000\000\000\000\000\000\000\000\000\030V\000\000\000\000\000\000\000\000\000\000\000\000\003\230\000\000\000\000\000\000\000\000\000\000\000\000\005(\000\000\000\000 \006\000\000\000\000\000\000,\208\000\000\000\000\000?\000\000\000\000\000\000#\134\000\000\000\000\000\000\000\000,\242\000\000\000\000\000\000\000\000\004\224\008\024\000\000-\166\000\000\000\000\000\000\000\000\024<\000F\000\000\024\184\000\000\000\000\013\214\000\000-\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\146\000\000\000\000%\240\000\000\000\000\000\000-\230\000\000\000\000\002\158\000\000\000\000\014^\000\000\025\132\000\000\000\000\"\198\000\000\000\000\000\000\000K\000\000\000\000&\178\000\000\000\000\000\000\000\000.$\000\000\000\000\000\000\000\000\005p\015D\000\000.p\000\000\000\000\000\000\000\000\000\000\000\000\015 \000\000\000\000\003\154\000\000\015\162\000\000\000K\000\000\000\000\003\238\0254\000\000\004\012\000\000\000\000\000\000\000\000\003f\000\000)\210\000\000\026\000\0022\026|\000\000\002\252\000\000\016\"\000\000\016\230\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\022\027J\004\232\027\198\000\000\000\000\000\000\006*\000\000\017f\000\000\004\130\000\000\000\000\000K\004\014\028\146\000\000\005\130\000\000\017\230\029J\000\000\000\000\018\170\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\030\008z\000\000\006\166\000\000\000\000\000\000\000\000\003\194\000\000\019\154\000\000\000\000\000\000\031j5P\000\000\000\000\000\000\030\216\000\000\000\000\000\000\000\000\015.\005\170\000\000\000\000.\164\000\000\000\000\000\000\000\000\006\210\000\000\000\0000T\000\000\000\000\000\000.\188\000\000\000\000\000-\000\000\000\000/:\000\000\000\000\n\022\006\244\000\000\000\000/x\000\000\000\000\006\174\031\208\000\000\006\252\000\000\000\000/\152\000\000\000\000\000\000\000\000\000\000\000\000\007\022\000\000\000\0006>\000\000\000\000\000\000/\192\000\000\000\000\000\000\000\000\000\000#\014\000\000\000\000\000\000\000\162\000\000\000\000\000\000/\196\000\000\000\000\n\174\007*\000\000\000\0000V\000\000\000\000\006\180\000\000\000\000\000\000\000\000\003f\005\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\134\000\000\020J\000\000\000\000\000\0005h\000\000\t\012\000\000\000\000\000\000\004t\000\000\000\000\000g\020\250\000\000\021\170\000\000\000\000\000\000\004\194\000\000\014>\005<\016\n\000\000\023Z\000\000\000\000\000\000\005\224\000\000*~\006\018+,\000\000+r\000\000\000\000\000\000\007J\000\000\026\200\007X\000\000\000\000\022l\013\214\007j\029T\000\000\030,\000\000\000\000\000\000\007\234\000\0003\176\008 \000\000\000\000\000\000\000c\000\000\000\000\000\000\000\000\000\000\002\208\000\000\000\000\002\186\000\000\003\024\000\000\000\000\000\000\003\018\000\000\000\000\000\000\000\000\000E\000\000\006\242\002\166\002\184\000\000\000\000\006\184\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\246\002B\000\000\000\000\000\025\000\000\000\000\000\000\004&\000\000\000\000\006j\006x\000\000\000\000\000\000\000\000\008\146\011&\000\024\000\000\012\172\000\000\000\000\000\000\000\000\000\000\000\000\007H\000\000\000\000\005\022\000\000\000\000\002\164\000\000\000\000\000\140\000\000\000\000\005\154\000\000\007\030\004J\005\140\000\000\000\000\0060\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\206\017\254\000\000\000\000\000\000\000\000\006^\000\000\000\000\007\138\000\000\000\000\000\000\019\252\000\000\000\000\t\130\021\144\0044\000\000\021\188\000\000\000\000\000\000\000\000\000\000\000\000\0007\000\000\007\166\007h\001\224\000\000\000\000\000\000\000\000\006\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000v\000\000\008\026\004r\006\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\142\000\000\000\000\014r\022@\000\000\000\000\000\000\000\000\001\230\000\000\003\018\000\000\n0\000\000\000\000\000\000\000\000\000\000\000\000\000\007\0114\000\000\000\000\011\222\000\000\000\000\000\000\000\000\007x\000\000\013B\000\000\000\000\000\000\000\000\003\198\000\000\000\000\000\000\000B\000\000\000\000\003\128\000\000\000\000\000\000\000\000\000\000\000\000\000\0000~\005\188\000\000\000\000\000\0000\142\000\000\000\000\016\140\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003f\000\000\000\000\000\000\000\000\000\000\000#\007\128\000g\007\212\013\136\003\214\000\000\000\000\000\204\001\150\003*\004\170\000\000\000\000\000\000\000\000\000\000\000\000\028\\\000\000\000\000\000\000\000\000\016\248\000\204\029\220\005\234\000\000\000\000\008(\000\000\022Z\000\000\000\000\007\204\000\000\000\000\000\000\007\128\000\000\004\012\000\000\004h!l\000\000\000\000\000\000\000\000\002\238\000\000\003\136\000\000\007\164\000\000\000\000\006\214\000\000\000\000\000\000\000\000\t\196\000\000\000\000\000\204\008\178\000\000\022\244\000\000\000K\004\164\000\000\000\000\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\0000\182\008$\000\000\001\178\000\000\000\000\000\000\000\000\000\000\001&\000\000\n\144\t$\011R\000\000\002n\011\212\000\000\t*\000\000\003\178\000\000\004,\000\000\004\248\000\000\000\000\000\000\000\000\000\000\008x\000\000\005\176\000\000\tD\000\000\006|\000\000\000K\005\006\000\000\000[\000\000\006<\005p\000\000\008\156\000\000\008\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\192\000\000\t \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\238\005\246\008\150\007<\000\000\007R\000\000\000\000\006\128\tT\000\000\006T\000\000\000\000\000\000\000\000\0074\000\000\000\000\000\000\000\000\000\000\007L\008\172\008\146\007\138\007\204\000\000\000\000\000\028\000\000\000\000\000\000\000\000\008\188\000\000\000\000"), (16, "\001\182\001\205\0006\000\\\004>\004T\0059\0018\005\184\001;\000^\002c\005:\001\129\000-\004\187\005\185\002c\005;\005=\003\014\000\n\004R\000\211\002\245\000\238\004U\004a\000-\001\131\002\245\004l\004\185\004\188\004a\003\251\000\211\004\203\000\236\002\245\000\017\000\005\004\203\000\016\003\015\000\t\001\184\000^\004j\004a\001\185\000\191\000_\0006\004\204\001=\000`\004\207\004a\004\204\001\132\003\011\004\207\004a\000\008\000\t\005\215\000^\001*\004C\000\213\003\012\004{\004a\000\214\005\216\001\131\001\182\001\205\0006\000^\000i\000\211\000\213\000\236\000\193\004b\000\214\004\240\005E\004\019\000-\000\211\004b\000\232\002[\003\\\003D\000\243\004\206\000'\000\227\001,\000&\000\252\004D\004\021\000D\004b\000D\005F\004\141\0026\001<\000\227\000\154\004\204\004b\004\243\004\207\004a\003\015\004b\001\184\001\135\000-\000^\001\185\004\142\000\213\004\145\004a\004b\000\214\0007\002J\000^\005/\0031\000\213\0007\005\207\002\245\000\214\002\246\001\198\0029\002:\002<\0007\002O\005\004\005\005\002\246\002P\001@\003\022\005H\001\199\001<\000\227\000j\0006\0007\001\182\001\205\005I\005c\000\253\000\152\000\227\005d\0012\003\139\000E\001\210\005\127\001%\000-\004b\0036\000\228\005;\005\128\003\014\000k\002\251\002T\000\168\001t\004b\003%\005f\000\244\000\228\003\185\0006\003:\003*\005p\005q\000\160\005h\002\255\003<\001\214\004E\000\246\003\015\001>\001\184\001%\002J\0006\001\185\000\160\004\235\000-\000\166\005\146\001x\003\252\001\198\004\246\0006\001\215\000-\002O\004\215\001\000\001\216\002P\001@\003\022\001\217\001\199\003\141\003j\005/\001\218\000\228\001\182\001\205\000^\003\023\003\254\004\t\0004\003X\001\001\000\228\000-\0007\005u\001\002\000-\0031\001\143\001\003\002[\003\\\003D\001\001\001\004\002T\0006\000\152\001c\003E\005\147\003d\000\191\000b\000\017\000-\003*\001\006\0006\000\160\003{\001U\003<\001\214\004\203\0053\003\015\004\192\001\184\004E\000\255\005y\001\185\002}\005z\001O\002\146\001\145\004\157\003\229\002J\004\204\004\193\001\215\004\207\004a\000\192\0007\001\216\000\237\001\198\005\029\001\217\000\160\001'\002O\000\166\001\218\003^\002P\001@\003\022\005\149\001\199\000\179\000-\000/\001z\0002\001\182\001\205\005I\005c\004i\000'\0007\005\151\000^\0006\003k\001\210\002\127\001%\000-\004\011\002\128\005~\005;\005\133\003D\004j\004a\002T\001E\000\253\0004\003%\005\153\002]\001@\001d\000\170\003$\003*\004b\004\232\000\160\005\155\001@\003<\001\214\001B\003\012\003\015\004\000\001\184\000\216\002J\000\\\001\185\001P\001m\000e\001A\001\182\001\203\0052\001\198\000\225\005\143\001\215\000-\002O\000\169\004X\001\216\002P\001@\003\022\001\217\001\199\004\141\003m\005\029\001\218\000\160\001l\001W\001o\003\023\004b\004\194\001X\003X\000\160\001Y\000\152\000\166\004\142\003^\004\145\004a\000^\004g\000\211\0023\000\231\000_\000^\002T\001\184\000`\004J\003E\001\185\003d\004Q\0006\002\141\000\160\003*\005/\0019\000\160\003{\001N\003<\001\214\0026\002}\000\\\002\142\002\150\004R\000\185\004O\000i\004U\004a\001O\004^\003f\000\160\004\235\002J\000\166\001@\001\215\000^\004Y\004\236\000\213\001\216\004\197\001\198\000\214\001\217\0024\001B\002O\004b\001\218\0028\002P\001@\003\022\005\139\001\199\003J\001i\004\138\001\182\001\205\002I\000^\005I\005c\002\127\003\012\000_\002R\002\128\000\227\000`\001*\000-\002\015\002\016\003\150\005;\005\133\003D\000\160\001l\0006\001o\002T\004b\003\012\004m\003E\002}\005\141\001e\002\150\002\015\002\016\003*\000i\001\198\000\160\003/\001@\003<\001\214\003\015\000j\001\184\001+\000-\000\191\001\185\001\199\005\031\001P\005\000\005 \001^\002\227\0025\000-\005\138\001\182\001\205\001\215\000\137\003}\005\t\005\n\001\216\000k\0006\003a\001\217\005$\002I\000-\0006\001\218\002\127\005;\005\133\003D\002\128\001\213\004i\001X\005\014\000\160\001Y\004\\\000\166\000\228\000-\003\254\000\138\000\\\004\163\0051\001\242\000e\004\238\004j\004a\002\141\002\206\003\015\002\204\001\184\004\178\004a\0024\001\185\002\169\003S\005Z\000m\002\142\000j\001\215\000\139\004\154\005\140\002b\000\140\001d\000\211\003\135\000\230\003S\000o\005\029\004c\001\218\001Z\004\001\002J\003x\002\207\004\248\000^\004\212\000k\005/\005\029\000_\001\198\005\002\003U\000`\000-\002O\0006\005*\002\018\002P\001@\003\022\005\139\001\199\002\015\002\016\004b\003T\001\182\001\205\000-\005I\005c\004b\000^\003z\002R\000\213\000i\003p\002\141\000\214\000-\002\211\001p\0007\005;\005\133\003D\002\169\002\172\001\187\002T\002\142\000\152\003x\003E\000-\005\141\001#\003\002\002J\005n\003*\002\173\001@\000\160\003/\000\227\003<\001\214\001\198\003\015\005\157\001\184\004\135\002O\005R\001\185\002\245\002P\001@\003\022\005\139\001\199\002\015\002\016\005W\005\142\003y\001\215\002\228\005I\005c\004\012\001\216\0006\002R\001@\001\217\000\160\004\235\000-\000\166\001\218\005]\0006\005^\000-\005U\002\231\000\160\005V\002T\000\166\002\214\003}\003E\000j\005\141\001\182\001\205\002\172\001*\003*\004\022\0007\000\160\003/\004\148\003<\001\214\003=\004\144\000-\004p\002\173\000\188\005;\005\133\003D\004\021\000k\002\017\000\160\002\243\004\149\003\001\000\228\0006\004\142\001\215\004\145\004a\0050\000\169\001\216\001,\005?\000-\001\217\0006\001U\002J\003\015\001\218\001\184\000\138\003\012\0006\001\185\000\169\001q\001\198\001\182\001\252\001O\003\128\002O\005X\005\150\003r\002P\001@\003\022\005\139\001\199\004\029\000m\0007\004\196\004\011\000\139\0031\005I\005c\000\140\004\148\000\152\002R\003p\000\160\000o\004\031\002W\004\193\0007\000-\000/\0000\0002\004\151\004b\001U\004\149\002T\001\196\000\160\000^\003E\001\184\005\141\001\182\001\205\001\185\0006\003*\001O\004\149\000\160\003/\004\141\003<\001\214\005\161\003\229\000-\0004\005\026\004i\005;\005\133\003D\000\169\000\160\004\133\004i\000\166\004\142\001@\004\145\004a\002\234\001\215\0006\002J\004j\004a\001\216\0007\003\144\001P\001\217\004j\004a\001\198\003\015\001\218\001\184\004 \002O\0007\001\185\005\180\002P\001@\003\022\005\139\001\199\002#\004[\000-\005\154\001\182\001\205\004\031\005I\005c\001[\000\160\001f\002R\004'\001X\003\146\000\160\001Y\000-\000\166\005\027\001@\002[\003\\\003D\0006\003\026\0006\002T\004)\0006\004b\003E\001P\005\141\004\194\004\152\004b\003\167\003*\001\198\005\186\000\160\003/\004b\003<\001\214\0006\003\015\003\144\001\184\0006\003\241\001\199\001\185\003\241\0022\005Z\005\196\000-\001[\005\187\001\\\003u\0006\001X\001\215\000\160\001Y\001@\000\166\001\216\004_\005\192\0006\001\217\004Y\004\132\002J\002}\001\218\001B\002\150\003\145\005\191\002\130\003\243\000-\001\198\003\242\002c\005(\001i\002O\004\184\005\201\004\155\002P\001@\003\022\005\139\001\199\004\141\0006\004\210\004\193\001\182\001\205\004`\005I\005c\004\185\004\188\004a\002R\000\160\001l\000^\001o\004\142\000-\004\145\004a\002I\002[\003\\\003D\002\127\005\205\000-\002T\002\128\004\156\005(\003E\002\139\005\141\002\166\004\166\002J\0007\003*\000-\001@\000\160\003/\004v\003<\001\214\001\198\003\015\000-\001\184\004t\002O\005R\001\185\0007\002P\001@\003\022\0007\001\199\004\004\003j\004\200\005B\002}\001\215\004*\002\150\003\023\004b\001\216\0007\002R\003\012\001\217\004-\005\203\002c\004b\001\218\005\\\0007\004)\003\175\005U\0046\000\160\005V\002T\000\166\0006\004\031\003E\001U\003d\001\182\001\205\000\152\004\201\003*\003\192\0048\000\160\003/\003\201\003<\001\214\001O\000^\000-\0007\004\199\002\127\002[\003\\\003D\002\128\003\211\004\213\005Y\005G\002\141\002\201\002\222\002\204\005)\001\215\003\236\005K\005\208\002\169\001\216\005e\004i\002\142\001\217\0055\005,\002J\003\015\001\218\001\184\003\012\000\160\004\133\001\185\000\166\005\211\001\198\0049\004j\004a\005\212\002O\004\214\002\207\002d\002P\001@\003\022\004\136\001\199\003h\003j\005w\0048\005\172\005)\001\182\001\205\003\023\000\160\005\220\002\229\002R\004<\005\172\004\253\0054\005,\001@\005\027\000-\000\000\005\172\004\169\002[\003\\\003D\000\152\002T\004\031\001P\000\000\003E\002}\003d\000-\002\150\005\130\0007\003*\005\130\002\172\000\160\003/\005\148\003<\001\214\002\141\004b\005X\003\015\000\160\001\184\005\130\000\000\002\173\001\185\001[\005\210\001a\002\142\005\193\001X\005\027\000\160\001Y\001\215\000\166\002J\005\195\005\172\001\216\005\209\000\160\001|\001\217\000\166\002I\001\198\005\144\001\218\002\127\005\136\002O\003\003\002\128\004\149\002P\001@\003\022\004\184\001\199\003\143\003j\004\203\005\152\000\000\000\000\001\182\001\205\003\023\003\007\000\000\000\000\002R\005\027\000\\\004\185\004\188\004a\000e\004\204\000-\000\000\004\207\004a\002[\003\\\003D\000\000\002T\000\000\000-\0003\003E\0002\003d\000\000\005\205\002\172\000\000\003*\000\000\000\000\000\160\003/\005\179\003<\001\214\004\202\000\000\002J\003\015\002\175\001\184\000\000\005\173\000\000\001\185\000\000\000^\001\198\0004\000-\005\175\000_\002O\004\129\001\215\000`\002P\001@\003\022\001\216\001\199\004\008\003j\001\217\004b\001\182\001\202\005\206\001\218\003\023\004b\004\203\000\152\002R\002\141\002\201\002\202\002\204\005\206\003\191\000i\000\000\002}\002\169\000\211\002\150\000\238\002\142\004\204\002T\000\000\004\207\004a\003E\000\000\003d\001\182\001\205\005\177\000\000\003*\000\186\000\000\000\160\003/\000\000\003<\001\214\002\207\000^\000-\001\184\000\000\000\000\005;\001\185\003\014\000\000\000\160\001)\000\000\000\166\000\211\000\000\000\229\000-\000^\001\215\000^\002J\002\127\000\213\001\216\000\000\002\128\000\214\001\217\000\000\000\000\001\198\003\015\001\218\001\184\000\000\002O\000\000\001\185\000\000\002P\001@\003\022\004b\001\199\005a\003j\003\235\002\172\000\000\005\145\001@\000j\003\023\000\227\000\000\000\000\002R\000^\000\000\000\000\000\213\002\173\001B\004\217\000\214\000\000\000\000\004\220\000\000\000\000\000\188\000\000\002T\001i\000\000\000k\003E\000\000\003d\000\000\000\000\000\169\000\000\003*\001\182\001\205\000\160\003/\004i\003<\001\214\000\227\004\203\000\000\000\000\000\000\000\160\001l\000-\001o\000\138\001\198\005;\000\000\003\014\004j\004a\000\000\002}\004\204\001\215\002\150\004\207\004a\001\199\001\216\000\000\000\000\002\141\001\217\000\000\000m\002J\000\000\001\218\000\139\000\000\000\160\003\015\000\140\001\184\002\142\001\198\000\228\001\185\000o\000\000\002O\000\000\000\000\000\000\002P\001@\003\022\005\132\001\199\005\131\000\000\004\233\001\182\001\205\000\000\002I\005I\005c\000\000\002\127\000\169\005\135\000\254\002\128\000\000\000\000\000-\000\000\004b\000\000\005;\000\000\003\014\000\000\000\228\004b\000\000\002T\000\000\000\000\004\203\003%\005\137\000\211\001\000\000\236\000\000\000\000\003*\001\182\001\203\000\160\003/\000\000\003<\001\214\003\015\004\204\001\184\000\000\004\207\004a\001\185\002\172\001\001\000\000\000\160\000\000\000\000\001\002\000\000\000\000\000\000\001\003\005\134\001\215\000\000\002\177\001\004\000\000\001\216\000\000\002J\002}\001\217\000\000\002\145\000^\000\000\001\218\000\213\000\000\001\198\000^\000\214\001\184\000\000\002O\000\000\001\185\000\000\002P\001@\003\022\005\132\001\199\000-\000/\001v\0002\001\182\001\205\000\000\005I\005c\000\000\002\141\000-\005\135\002\208\004b\000\227\000\000\000\000\000-\002\169\000\000\000^\002[\002\142\003\014\002\127\000\000\000\000\002T\002\128\0004\004\127\003%\005\137\000\000\004\241\000\000\000\000\000\000\003*\004i\002J\000\160\003/\002\210\003<\001\214\000\000\003\015\000\000\001\184\001\198\000\000\000\000\001\185\000\000\002O\004j\004a\000\000\002P\001@\003\022\005\132\001\199\000\000\001\215\000\000\000\000\001\182\001\205\001\216\005I\005c\000\000\001\217\000\000\005\135\000\000\000\000\001\218\004\014\000\000\000-\000\000\003\138\002\216\002[\001\198\003\014\000\000\000\000\002\172\002T\000\000\000\228\000\000\003%\005\137\002}\000\000\001\199\002\150\000\000\003*\000\000\002\173\000\160\003/\000\000\003<\001\214\004\203\003\015\000\000\001\184\000\000\004b\000\000\001\185\004\244\000\000\002\141\000\000\000\000\000\211\000\000\000\238\000\000\004\204\000\000\001\215\004\207\004a\000\000\002\142\001\216\000\000\000-\002J\001\217\001@\005(\002I\000\000\001\218\003\136\002\127\000\000\001\198\003\138\002\128\000\152\001B\002O\000\000\000\000\000\000\002P\001@\003\022\000\000\001\199\001\001\001i\000\000\001\182\001\205\001\215\000^\000\000\003\023\000\213\002Y\000\000\003\127\000\214\001\008\000\000\000\000\000-\000\000\001\220\000\000\002[\003\t\003\014\000\160\001l\000\000\001o\002T\004b\000\000\002c\003%\003\129\000\000\000\160\001~\000\243\000\166\003*\000\227\002J\000\160\003/\0006\003<\001\214\003\015\000\000\001\184\000\000\001\198\000\211\001\185\000\238\000\000\002O\000\000\000\000\000\000\002P\001@\003\022\004}\001\199\000\000\001\215\000\000\001\182\001\205\000\000\001\216\000\000\003\023\000\000\001\217\003'\003\127\000\000\000\000\001\218\002\141\000-\000\000\002\217\000\000\002[\003(\003D\002}\002\169\000\000\002\150\002T\002\142\000\000\000^\003%\003\129\000\213\000\000\000\000\004\141\000\214\003*\000\000\000\000\000\160\003/\000\000\003<\001\214\003\015\000\000\001\184\000\000\005)\000\000\001\185\004\142\000\228\004\145\004a\002}\000\000\000\000\002\150\005+\005,\000\000\000\227\001\215\0013\000^\000\000\004\251\001\216\002\127\002J\000\000\001\217\002\128\000\000\000\\\000\000\001\218\000\246\000q\001\198\000\000\000\000\000\000\000\000\002O\0007\000-\000\000\002P\001@\003\022\000\000\001\199\000\160\002\172\000\000\001\182\001\205\002I\001\000\000\000\003\023\002\127\000\000\003G\003I\002\128\000\000\002\173\000\000\000-\000\000\004b\000\000\002[\003(\003D\000-\000^\001\001\000\000\002T\000\000\000_\001\002\003%\003K\000`\001\003\000\000\000\000\003\016\003*\001\004\002J\000\160\003M\000\000\003<\001\214\003\015\000\228\001\184\000\000\001\198\002c\001\185\003\166\003\020\002O\000\000\000\000\000i\002P\001@\003\022\000\000\001\199\0006\001\215\000\000\001\182\001\205\000\000\001\216\002\141\003\023\004\024\001\217\003L\002R\000\000\000\000\001\218\000\000\000-\000\000\000\000\002\142\002[\003(\003D\000\000\000\000\000\000\000\000\002T\000\000\000\000\001\000\003E\000\000\003F\000\000\000\000\000\000\000\000\003*\000\000\002\141\000\160\003/\002\168\003<\001\214\003\015\000\000\001\184\002\169\001\001\000\000\001\185\002\142\000\211\001\002\000\238\000\000\000\000\001\003\004\226\000\000\000\000\000\000\001\004\001\215\001\182\001\205\000\152\000\000\001\216\000\000\002J\000j\001\217\000\000\000\211\000\000\000\236\001\218\000-\000\000\001\198\000\000\002[\003\\\003D\002O\002\172\000\000\000\000\002P\001@\003\022\000\000\001\199\000\000\000k\000^\001@\000\000\000\213\002\179\000\000\003\023\000\214\000\000\000\000\002R\0007\003\015\003\172\001\184\000\000\000\160\001\128\001\185\000\166\000\000\000\211\000^\000\238\002\172\000\213\002T\000\000\000\000\000\214\003E\000\000\003F\000\000\000\227\000\000\000\000\003*\002\173\002J\000\160\003/\000\000\003<\001\214\001/\000\000\000\160\003\184\001\198\003\190\005\023\002}\000\000\002O\002\144\000\227\003>\002P\001@\003\022\000\000\001\199\000\000\001\215\000^\001\182\001\205\000\213\001\216\000\000\003\023\000\214\001\217\003B\002R\000\000\000\000\001\218\000\000\000-\000\000\000\000\000\000\002[\003\\\003D\000\000\000\000\000-\000\000\002T\000\000\005(\000\000\003E\000^\003F\000\000\000\227\002\127\000\000\003*\002J\002\128\000\160\003/\000\000\003<\001\214\003\015\000\000\001\184\001\198\000\228\000\000\001\185\000\000\002O\002b\000\000\000\000\002P\001@\003\022\000\000\001\199\000\000\003c\001\215\001\182\001\205\000\000\000\000\001\216\003\023\000\228\000\\\001\217\002R\004\026\000\182\000\000\001\218\000-\000\000\000\000\000\000\002[\003\\\003D\000\000\000\000\000-\000\000\002T\000\000\000\000\000\000\003E\000\000\003d\001\000\000\000\000\000\000\000\003*\000\000\000\000\000\160\003/\000\000\003<\001\214\003\015\000\000\001\184\000\000\000\000\000\228\001\185\000^\001\001\000\000\001\028\000\000\000_\001\002\000\000\000\000\000`\001\003\000\000\001\215\001\182\001\205\001\004\002\141\001\216\000\000\000\000\002J\001\217\000\000\001\001\005\021\000\000\001\218\000-\000\000\002\142\001\198\002[\003\130\003D\000i\002O\000\000\001\004\000\000\002P\001@\003\022\000\000\001\199\000\\\003e\001\000\000\000\000q\001@\000\000\004i\003\023\000\000\000\000\000\000\002R\003\015\000\000\001\184\005+\005<\000\000\001\185\000\000\000\000\001\001\000\000\004j\004a\000\000\001\002\002T\000\000\000\000\001\003\003E\000\000\003d\000\000\001\004\000\000\000\000\003*\002J\000\000\000\160\003/\000^\003<\001\214\000\000\003\132\000_\001\198\000\160\002\243\000`\003\001\002O\000\000\000\000\000\000\002P\001@\003\022\000\000\001\199\000\000\003w\001\215\001\182\001\205\000\152\000j\001\216\003\023\000\000\000\000\001\217\002R\000\000\000i\000\000\001\218\000-\001\182\001\203\004b\002[\003\130\003D\000\000\000\000\002}\000\000\002T\002\150\000k\000\000\003E\000\000\003d\001\182\001\205\000\000\000\000\003*\002J\000\000\000\160\003/\000\\\003<\001\214\003\015\000e\001\184\001\198\000\160\001\141\001\185\000\166\002O\000\000\000\000\000-\002P\001@\003\022\000^\001\199\001\184\000\000\001\215\000\000\001\185\000\000\000^\001\216\003\023\000\000\002\127\001\217\002R\000\000\002\128\000^\001\218\001\184\003\134\000\000\000\000\001\185\000\000\000\000\000^\000\000\000\000\000\000\002T\000_\000j\000\000\003E\000`\003\133\000\000\000\000\000\\\000\000\003*\000\000\000\181\000\160\003/\000\000\003<\001\214\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000k\000\000\000\000\000\000\000i\001\182\001\205\000\000\000\000\000\000\000\000\004\161\001\215\003\152\000\000\001\210\000\000\001\216\000\000\000-\002J\001\217\000\000\002[\003(\003D\001\218\000^\000\000\000\000\001\198\000\000\000_\000\000\000-\002O\000`\001j\000\000\002P\001@\003\022\000\000\001\199\000\000\001\198\000m\000\000\000\000\003\015\000\000\001\184\003\023\002\141\000\000\001\185\002R\000\000\001\199\000\000\000r\000i\001\198\000\000\0004\000\000\002\142\000\000\001\182\001\203\000\000\000\000\002T\000\000\000\000\001\199\003E\000\000\003\133\000\000\004i\000\152\000\000\003*\000j\000\000\000\160\003/\001\212\003<\001\214\000\000\000\000\001\182\001\205\000\000\000\000\004j\004a\000\000\000\000\000\000\000\000\000\183\000\000\000\000\000\000\000-\000k\000\000\001\215\002[\000^\003\014\001\184\001\216\000\000\000\000\001\185\001\217\000\000\000\000\001\214\000\000\001\218\001\204\000\000\000\160\001-\000\000\000\166\000\000\000\000\000\138\000\000\002\172\000\000\003\015\000\000\001\184\002J\000j\001\215\001\185\000\000\002}\000\000\001\216\002\143\002\181\001\198\001\217\000\000\000\000\000m\002O\001\218\004b\000\139\002P\001@\003\022\000\140\001\199\000\000\000k\000\000\000\\\000o\000\000\004\002\000g\003\023\000\000\003\138\001@\002R\000\000\000\000\000\000\000\000\001\182\001\205\000\000\000\000\002}\000\000\001B\002\150\000^\000\000\000\000\002T\002\127\000\000\000-\003E\002\128\003F\002[\000\000\003\014\002}\003*\000\000\002\150\000\160\003/\000\\\003<\001\214\000^\000]\001\198\000\000\000\000\000_\000\000\000\000\000\000\000`\000\160\001l\001s\001o\003\015\001\199\001\184\002J\000^\001\215\001\185\000\000\002\127\000\000\001\216\000\000\002\128\001\198\001\217\000\000\000\000\000\000\002O\001\218\000i\000^\002P\001@\003\022\002\127\001\199\000^\000\000\002\128\000\000\000\000\000_\004\016\000\000\003\023\000`\003\138\000\000\003\127\000\000\004\173\000\000\000\000\001\182\001\205\000\000\000\000\000\211\000\000\000\212\000\000\000\000\000\000\000\000\002T\000\000\004i\000-\003%\003\129\000i\002[\000\000\003\014\002\141\003*\000\000\001\215\000\160\003/\000\000\003<\001\214\004j\004a\000\000\000\000\002\142\004i\000\000\000\000\001\222\000\000\000\000\000\000\000\000\000\000\003\015\000\000\001\184\002J\000^\001\215\001\185\000\213\004j\004a\001\216\000\214\000j\001\198\001\217\000\000\000\000\002\141\002O\001\218\000\000\000\000\002P\001@\003\022\000\000\001\199\000\000\000\000\000\000\002\142\000\000\000\000\004\018\002\141\003\023\000k\003\138\000\227\003\127\000\000\000\000\000\000\000\000\001\182\001\205\004b\002\142\000\000\000\000\000\000\000\000\005D\000j\000\000\002T\000\000\004i\000-\003%\003\129\000l\002[\003(\003D\000\000\003*\000-\004b\000\160\003/\002[\003<\001\214\004j\004a\000\000\000k\000\000\000\000\002}\000\000\000m\002\150\000\000\000\000\000\000\000\149\003\015\000\000\001\184\002J\000\000\001\215\001\185\000\000\000o\0040\001\216\002\172\000\000\001\198\001\217\000\000\000\000\000\000\002O\001\218\000\000\000\000\002P\001@\003\022\002\183\001\199\000\\\002\172\000\000\000\228\000q\000\000\001\182\001\205\003\023\002I\000\000\000\000\003\127\002\127\005g\002\185\000\000\002\128\000\000\004b\000-\000\000\000\000\000\000\002[\003(\003D\000\000\002T\000\000\000\000\000\000\003%\003\129\000\000\000\000\000\000\000\000\000\000\003*\004\182\000\000\000\160\003/\000^\003<\001\214\000\000\000\000\000_\003\015\000\000\001\184\000`\000\000\000\000\001\185\000\211\000\000\000\238\000\000\000\000\004\180\000\000\002J\000\000\001\215\003\147\001\182\001\205\000\000\001\216\000\000\000\000\001\198\001\217\000\000\000\000\000i\002O\001\218\000\000\000-\002P\001@\003\022\002[\001\199\003D\000\000\000\000\000\000\000\000\001@\003\022\000\000\003\023\000\000\000\000\000\000\002R\000^\001\182\001\201\000\213\003\023\000\000\000\000\000\214\000\000\002\141\000\000\003\015\002\208\001\184\000\000\002T\000\000\001\185\002\169\003E\000-\003F\002\142\000\000\000\000\000\000\003*\004\224\0041\000\160\003/\000\000\003<\001\214\000\227\003*\000\000\000\000\000\160\003/\002J\003<\000\000\002\210\000\000\000^\000\000\001\184\000\000\000\000\001\198\001\185\000\000\001\215\000\000\002O\000\000\000j\001\216\002P\001@\003\022\001\217\001\199\000\000\000\000\000\000\001\218\000\000\001\182\001\205\000\000\003\023\000\000\001U\000\000\002R\000\000\000\000\000\000\003H\000k\000\000\000-\000\000\002\215\000\000\002[\001O\003\014\000\000\002\172\002T\000\000\000\000\000\000\003E\000\000\003F\000\000\000\000\000\000\002J\003*\000\000\002\173\000\160\003/\000\000\003<\001\214\000\000\001\198\003\015\000\228\001\184\000\000\002O\000\000\001\185\000\000\002P\001@\003\022\000\000\001\199\000\000\000m\000\000\000\000\001\215\001\182\001\205\000\000\003\023\001\216\000\000\000\000\003\149\001\217\004\028\000t\003\013\000\000\001\218\000-\001\198\000\000\000\000\002[\000\000\003\014\000\000\000\000\002T\000\000\000\000\000\000\003E\001\199\003\151\001@\001\000\000\000\000\000\003*\000\000\000\000\000\160\003/\000\000\003<\001\214\001P\000\000\003\015\000\000\001\184\000\000\000\000\000\000\001\185\001\001\000\000\000\000\000\000\000\000\001\002\000\000\000\000\000\000\001\003\001\215\001\182\001\205\000\000\001\004\001\216\000\000\000\000\001[\001\217\001\137\000\000\002J\001X\001\218\000\160\001Y\000\000\000\166\000\000\000\000\003R\001\198\000\000\000\000\000\000\000\000\002O\000\000\000\000\000\000\002P\001@\003\022\000\000\001\199\000\000\000\000\000\000\000\000\000\000\001\182\001\205\000\000\003\023\002I\000\000\001\184\003#\000\000\000\000\001\185\003)\000\000\000\000\000-\000\000\000\000\000\000\002[\000\000\003\014\000\000\000\000\002T\000\000\000\000\000\000\003%\003&\000\000\000\000\000\000\000\000\002J\003*\000\000\000\000\000\160\003/\000\000\003<\001\214\000\000\001\198\003\015\000\000\001\184\000\000\002O\000\000\001\185\000\000\002P\001@\003\022\000\000\001\199\000\000\000\000\000\000\000\000\001\215\001\182\001\205\000\000\003\023\001\216\000\000\000\000\003#\001\217\000\000\000\000\000\000\000\000\001\218\000-\000\000\002}\000\000\002[\002\150\003\014\000\000\000\000\002T\000\000\000\000\000\000\003%\003&\000\000\000\000\000\000\000\000\002J\003*\000\000\000\000\000\160\003/\000\000\003<\001\214\000\000\001\198\003\015\000\000\001\184\000\000\002O\000\000\001\185\000\000\002P\000\000\000\000\000\000\001\199\000\000\000\000\000\000\000^\001\215\001\182\001\205\002\127\000\000\001\216\000\000\002\128\002R\001\217\000\000\000\000\002J\002}\001\218\000-\002~\000\000\000\000\002[\000\000\003\014\001\198\000\000\002T\000\000\000\000\002O\000\000\000\000\000\000\002P\001@\003\022\000\000\001\199\000\000\000\000\000\000\000\211\000\000\000\238\001\214\000\000\003\023\003\015\000\000\001\184\003#\000\000\000\000\001\185\000\000\000\000\000\000\000\000\000\000\000^\000\000\000\000\000\000\002\127\001\215\000\000\002T\002\128\000\000\001\216\003%\003&\000\000\001\217\000\000\000\000\002J\003*\001\218\000\000\000\160\003/\000\000\003<\001\214\000^\001\198\000\000\000\213\000\000\000\000\002O\000\214\000\000\000\000\002P\001@\003\022\000\000\001\199\000\000\000\000\002\141\000\000\001\215\003g\001\182\001\205\003\023\001\216\000\000\000\000\003`\001\217\000\000\002\142\000\000\000\000\001\218\000\227\000-\000\000\000\000\000\000\002[\000\000\003\014\000\000\002T\000\000\000\000\000\000\003%\003b\000\000\000\000\000\000\000\000\002J\003*\000\000\000\000\000\160\003/\000\000\003<\001\214\000\000\001\198\000\000\003\015\000\000\001\184\002O\000\000\000\000\001\185\002P\001@\003\022\002\141\001\199\000\000\000\000\000\000\000\000\001\215\003_\001\182\001\205\003\023\001\216\000\000\002\142\003`\001\217\000\000\000\000\000\000\000\000\001\218\000\000\000-\000\000\002\172\000\\\002[\000\000\003\014\000g\002T\000\000\000\000\000\000\003%\003b\000\000\000\000\002\187\000\228\000\000\003*\000\000\000\000\000\160\003/\000\000\003<\001\214\000\000\000\000\000\000\003\015\000\000\001\184\000\000\000\000\000\000\001\185\000\000\000\000\000\000\000\000\000\000\000\000\004,\000\000\000\000\001\215\000^\000\000\000\000\000\000\001\216\000_\000\000\000\000\001\217\000`\000\000\000\000\002J\001\218\002}\000\000\000\000\002\150\001\000\000\000\000\000\000\000\001\198\000\000\000\000\000\000\000\000\002O\000\000\000\000\000\000\002P\001@\003\022\000i\001\199\000\000\000\000\001\001\000\000\003s\001\182\001\205\001\002\003\023\000\000\000\000\001\003\003t\000\000\000\000\000\000\001\004\000\000\000\000\000-\000\000\002}\002I\002[\002\150\003\014\002\127\000\000\002T\000\000\002\128\000\000\003%\003v\000\000\000\000\000\000\000\000\002J\003*\000\000\000\000\000\160\003/\002}\003<\001\214\002\150\001\198\003\015\000\000\001\184\000\000\002O\000\000\001\185\000\000\002P\001@\003\022\000\000\001\199\000\000\000\000\000\000\002I\001\215\003q\000\000\002\127\003\023\001\216\000\000\002\128\003`\001\217\000\000\000\000\000j\000\000\001\218\000\000\000\000\000\000\000\000\000\000\003~\000\000\000^\000\000\002T\000\000\002\127\000\000\003%\003b\002\128\001\182\001\205\000\000\000\000\003*\000k\000\000\000\160\003/\000\000\003<\001\214\000\000\000\000\000-\000\000\000\000\000\000\002[\000-\003\014\000\000\000\000\002[\000\000\000\000\002\141\002\201\0057\002\204\000l\001\215\000\000\000\000\000\000\002\169\001\216\000\000\000\000\002\142\001\217\000\000\000\000\002J\003\015\001\218\001\184\000\000\000\000\0040\001\185\000m\000\000\001\198\000\000\000\000\000n\000\000\002O\000\000\002\207\000\000\002P\001@\003\022\000o\001\199\000\000\000\000\002\141\000\000\000-\002\171\001\182\001\205\003\023\000\000\000\000\002\169\003\127\000\000\003\131\002\142\005@\000\000\000\000\000\000\000-\000\000\000\000\000\000\002[\002\141\003\014\000\000\002T\000\000\000\000\000\000\003%\003\129\000\000\000\000\000\000\000\000\002\142\003*\000\000\002\172\000\160\003/\000\000\003<\001\214\000\000\000\000\000\000\003\015\002}\001\184\000\000\002\150\002\173\001\185\000\000\001U\000\000\000-\000\000\000\000\000\000\002[\000\000\001\215\002}\002J\000\000\002\150\001\216\001O\000\000\000\000\001\217\000\000\000\\\001\198\000\000\001\218\000e\000\000\002O\002\172\000\000\000\000\002P\001@\003\022\0040\001\199\000\000\001@\003\022\000^\000\000\000\000\002\173\002\127\003\023\000\000\000\000\002\128\003\127\003\023\000\000\002\151\000\000\000\000\000\000\002I\000\000\000\000\000\000\002\127\000\000\000\000\000\000\002\128\002T\000^\000\000\000\000\003%\003\129\000_\000\000\000\000\0043\000`\003*\001\182\001\205\000\160\003/\003*\003<\001\214\000\160\003/\002J\003<\000\000\000\000\001@\000-\000\000\000\000\000\000\003\165\001\198\000\000\000\000\000\000\000i\002O\001P\001\215\000\000\002P\001@\003\022\001\216\001\199\000\000\000\000\001\217\000\000\003\197\000\000\000\000\001\218\003\023\000\000\000\000\003\200\005A\001\184\000\000\000\000\000\000\001\185\000\000\001[\000\000\002_\000\000\000\000\001X\000\000\000\160\001Y\002T\000\166\000\000\002\141\003%\005C\003\206\000\000\001@\003\022\000\000\003*\001\182\001\205\000\160\003/\002\142\003<\001\214\002\141\003\023\000\000\002\220\000\000\000\000\000\000\000-\000\000\002\169\000\000\003\165\000\000\002\142\002\224\003\244\000\000\000\000\001\210\001\215\001%\000\000\000\000\000j\001\216\0045\000\000\000\000\001\217\000\000\003\248\000\000\003*\001\218\000\000\000\160\003/\003\200\003<\001\184\000\000\000\000\002\164\001\185\001\182\001\205\000\000\000k\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000-\000\\\003\206\000\000\003\165\000e\000\000\001\198\002\172\000\000\000\000\000\000\000\000\000\000\000\138\000-\000\000\001@\003\207\000\000\001\199\000\000\002\189\003\199\002\172\000\000\000\000\000-\000\000\003\208\003\200\000\000\001\184\003\246\000\000\000m\001\185\000\000\002\173\000\139\000\000\000\000\000\000\000\140\000\000\000^\000\000\000\000\000\000\000o\000_\000\000\000\000\003\206\000`\002}\000\000\000\000\002\150\000\000\003\222\000\000\000\000\000\160\003\247\000\000\003\234\001\214\000\000\000\000\000\000\000\000\000\\\000\\\001\182\001\203\000e\000e\000\000\000i\001\198\001U\000\000\000\000\000\000\000\000\000-\001\215\000\000\000\000\001@\003\207\001\216\001\199\000\000\001O\001\217\000\000\000\000\000^\000\000\001\218\003\208\002\127\000\000\000\000\003\220\002\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000^\000^\000^\000\000\001\184\000_\000_\000\000\001\185\000`\000`\000\000\000\000\000\000\000\000\001\198\000\000\003\222\000\000\000\000\000\160\003\227\000\000\003\234\001\214\001@\003\207\000\000\001\199\000\000\000\000\000\000\000\\\000\000\000i\000i\000e\003\208\000\000\000\000\000\152\003\220\000\000\000j\001\215\000\000\000-\000\000\000\000\001\216\000\000\000\000\001@\001\217\000\000\000\000\002j\000\000\001\218\000\155\000\156\000\158\000\159\000\000\001P\000\000\000\000\000k\003\222\000\000\000\000\000\160\003\227\000\000\003\234\001\214\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\002\141\000`\000\160\000\165\000\000\000\166\000-\001[\000\138\002\237\000\000\001\215\001X\002\142\000\160\001Y\001\216\000\166\000\000\001\198\001\217\000\000\000\000\000\000\000\000\001\218\000i\000\152\000\000\000m\000j\000j\001\199\000\139\000\000\000\000\000\000\000\140\000\000\000\000\000\\\001\182\001\203\000o\000e\000\171\000\155\000\218\000\158\000\159\000\188\000\000\000\000\000\000\000k\000k\000\000\000\000\000\\\000\000\000\000\005Q\000e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000-\000\160\000\165\000\000\000\166\000\000\000\000\000\138\000\138\000\000\002\172\000\000\000^\000^\000\000\001\184\000\211\000_\000\236\001\185\000\000\000`\002}\000\000\002\191\002\150\000\000\001\215\000m\000m\000^\000\152\000\139\000\139\000j\000_\000\140\000\140\000\000\000`\000\000\001\224\000o\000o\000\171\000\000\000i\000\000\000\000\000\000\000\155\001\189\000\158\000\159\000\000\000\000\000\000\000\\\000k\000\000\000^\000e\000\000\000\213\000i\000\000\002I\000\214\000\000\000\000\002\127\000-\000\000\000\000\002\128\001@\000\000\000\160\000\165\000\000\000\166\000\000\000\000\000\138\000\000\000\000\000\000\005R\000\000\000\000\000\000\000\000\000\000\000\\\000\227\000\000\000\000\000e\000\000\000\000\000\000\000^\000\000\000\000\000m\000\000\000_\000-\000\139\000\000\000`\000\000\000\140\000\000\001\198\000\000\000\000\002\162\000o\005U\000\171\000\160\005V\000\000\000\166\000\000\000j\001\199\000\000\000\\\000\000\000\000\000\000\000e\000\000\000i\000\000\000^\000\000\000\000\000\000\000\152\000_\000-\000j\002\164\000`\000\000\000\000\000\000\000k\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\155\002L\000\158\000\159\000\000\000\000\000\000\002\141\000k\000\000\002\208\000i\000\000\000^\000\228\000\138\002\169\000\000\000_\000\000\002\142\000\000\000`\000\000\000\000\000\000\000\000\000\160\000\165\000\000\000\166\000\000\000\000\000\138\001\215\000\000\000m\000\000\000\000\000\000\000\139\002\210\000\000\000-\000\140\000\000\000\000\000i\001\226\000\000\000o\000\000\000\152\000\000\000m\000j\000\000\000\000\000\139\000\000\000\000\000\000\000\140\000\000\000\000\000\000\000\000\000\000\000o\000\000\000\171\000\155\002\132\000\158\000\159\000\000\000\000\000\000\000\000\000k\000\000\000\000\001\001\002\213\002}\000\000\000\000\002\150\000\152\002\172\000\000\000j\000\000\000\000\000\000\000\000\001\n\001U\000\160\000\165\000\000\000\166\000\000\002\173\000\138\000\000\000\000\000\155\003,\000\158\000\159\001O\000\000\000\000\000\000\000k\001\182\001\203\000\000\000\000\000\000\000\000\000\000\000\000\000\152\000m\000\000\000j\000^\000\139\000\000\000\000\002\127\000\140\000\160\000\165\002\128\000\166\000\\\000o\000\138\000\171\000e\000\155\003\224\000\158\000\159\000\000\000\000\000\\\000\000\000k\000-\000e\000\000\002}\000\000\000\000\002\150\000\000\000^\000m\001\184\000-\000\000\000\139\001\185\000\000\000\000\000\140\000\160\000\165\000\000\000\166\000\000\000o\000\138\000\171\000\000\000\000\000\000\000\000\000^\000\000\001@\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\000^\000\000\000\000\001P\000m\000_\000^\000\000\000\139\000`\002\127\000\\\000\140\000\000\002\128\000g\000\000\000\000\000o\000\000\000\171\000\000\000\000\000i\000\000\001\182\001\200\000\000\000\000\000\000\001[\000\000\002\248\000\000\000i\001X\002\141\000\160\001Y\000\000\000\166\001\182\001\205\000\000\001#\001%\000\000\000\000\000\211\002\142\000\236\000\000\000\000\000\\\000\000\000^\000\000\000e\000\000\000\000\000_\003P\000\000\000\000\000`\000\000\000\\\000-\001\198\000^\000e\001\184\000\000\000\000\000\000\001\185\000\000\000\000\000\000\000\000\000-\001\199\000\000\000\000\000\000\002I\000\000\001\184\000\000\000i\000\000\001\185\000^\000\000\000\000\000\213\000\000\000^\000\000\000\214\000\152\000\000\000_\000j\000\000\000\000\000`\002\141\000\000\000\000\000^\000\152\000\000\000\000\000j\000_\000\000\000\000\002\172\000`\002\142\000\000\000\188\000\000\000\000\000\000\000\227\000k\000\000\000\000\000\173\000i\002\193\000\159\000\000\003V\000\000\000\000\000k\001\210\000\000\000\\\000\000\000\000\000i\000e\000\160\001'\001\215\000\166\000\000\000\000\000\138\000\000\000\000\000-\000\000\000\160\000\165\000-\000\166\000\000\001\228\000\138\000\000\000\000\000\000\000\000\000\000\000j\001\198\000\000\000\000\000m\000\000\000\000\002J\000\139\000\000\000\000\000\000\000\140\000\000\001\199\000m\000^\001\198\000o\000\139\002\172\000_\002O\000\140\000k\000`\002P\000\000\000\000\000o\001\199\000\171\000\000\000\000\002\195\000\000\000\000\000\228\000\000\000\152\000\000\000\000\000j\003X\001U\000\000\000\000\000\000\000\000\000l\000i\000\000\000\152\000\000\000\000\000j\000\000\000\000\001O\002T\000\000\000\195\000\000\000\000\000\000\000\000\000k\000\000\000\000\000\\\000m\000\000\000\000\000e\000\195\000\148\000\000\001\214\000\000\000k\000\000\000\000\000\000\000-\000o\000\160\000\197\000-\000\166\000\000\000\000\000\138\000\000\000\000\001\182\001\205\000\000\001\215\000\160\000\234\000\000\000\166\001\216\000\000\000\138\001\001\001\217\000\000\000\000\000\000\000\000\001\218\000m\000^\002B\004\013\000\139\000\000\000_\001\012\000\140\000\000\000`\000\000\000\000\000m\000o\000\152\000\000\000\139\000j\001@\000\000\000\140\000\000\000\000\000\000\000\000\002I\000o\001\184\001U\000\000\001P\001\185\000\000\000\000\000i\000\\\000\183\000\000\000\000\000e\000\000\000k\001O\000\000\000\000\000\000\000\000\000\000\000\000\000-\000\000\000\000\000\000\000\000\000\000\000\000\000\211\001[\000\236\003\029\000\160\0016\001X\000\166\000\160\001Y\000\138\000\166\000\000\000\000\000\000\000\000\000\000\001\182\001\205\000\000\000\000\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000m\000`\000\000\000\000\000\139\000\000\002B\003Y\000\140\001\182\001\203\000\000\000\000\000^\000o\000\000\000\213\000\000\000\000\000\000\000\214\000\000\000\000\000\000\000\152\000\000\000i\000j\001@\002J\002I\000\000\001\184\000\000\000\000\000\000\001\185\000\000\000\000\001\198\001P\000\000\001\182\001\205\002O\000\000\001\165\000\227\002P\000\000\000\000\000k\001\199\000^\000\000\001\184\000\000\000\000\000\000\001\185\000\000\000\000\002B\003O\000\000\002R\000\000\001[\000\000\0033\000\160\001\167\001X\000\166\000\160\001Y\000\138\000\166\000\000\000\000\000\000\002T\000\000\000\000\000\000\000\000\002I\000\000\001\184\000\000\000-\001k\001\185\0002\000\000\001\182\001\205\000m\000\000\001\214\000\000\000\139\000\000\000\152\000\000\000\140\000j\000\000\000\000\000\000\000\000\000o\000\000\000\000\000\000\002B\002C\000\000\000\000\001\215\0004\002J\000\000\000\000\001\216\001\165\000\000\000\228\001\217\000\000\000k\001\198\000\000\001\218\000\000\000\000\002O\000\000\000\000\002I\002P\001\184\000\000\000\000\001\199\001\185\000\000\000\000\000\000\000\160\001\250\000\000\000\166\000\000\001\198\000\138\000\000\002R\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\199\001\182\001\205\000\000\000\000\000\000\002T\000\000\000\000\000m\002J\000\000\000\000\000\139\000\000\000\000\000\000\000\140\000\000\000\000\001\198\002B\002N\000o\001\214\002O\000\\\000\000\001\001\002P\000e\000\000\000\000\001\199\000\000\000\000\000\000\000\000\000\000\000\000\000-\000\000\001\014\000\000\001\215\002I\002R\001\184\000\000\001\216\000\000\001\185\000\000\001\217\000\000\000\000\000\000\000\000\001\218\000\000\000\000\000\000\002T\002J\001@\000\000\000\000\001\215\000\000\000\000\000^\000\000\000\000\001\198\000\000\000_\001B\000\000\002O\000`\001\214\001\230\002P\000\000\000\000\000\000\001\199\001i\000\\\000\000\000\\\000\\\000e\000\000\000e\000q\000\000\000\000\000\000\002R\001\215\000\000\000-\000\000\000i\001\216\001\182\001\205\000\000\001\217\000\160\001l\000\000\001o\001\218\002T\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002B\003[\000\000\000\211\000\000\000\236\000^\001\214\000^\000^\002J\000_\000\000\000_\000_\000`\000\000\000`\000`\000\000\001\198\000\000\000\000\000\000\002I\002O\001\184\001\215\000\134\002P\001\185\000\000\001\216\001\199\000\000\000\000\001\217\000\000\000\000\000\000\000i\001\218\000i\000i\000\000\000\000\002R\000^\000\000\000\000\000\213\000\000\000\000\000\000\000\214\000\152\000\000\000\000\000j\000\000\000\000\000\000\002T\000\000\000\000\000\000\001\182\001\205\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002m\000\000\000\000\001\214\000\227\000k\001\182\001\183\000\000\002B\004\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\215\000\160\002o\000\000\000\166\001\216\000\000\000\138\000\000\001\217\002I\000\000\001\184\000\000\001\218\002J\001\185\000\152\000\000\000\000\000j\000\000\000j\000j\000\000\001\198\000\000\000^\000m\001\184\002O\000\000\000\139\001\185\002P\000\000\000\140\000\000\001\199\002m\000\000\000\137\000o\000\000\000k\000\000\000k\000k\000\000\000\000\000\000\002R\000\000\001\182\001\205\000\000\000\000\000\000\000\000\000\000\000\000\000\228\000\000\000\160\002\148\000\000\000\166\002T\000\000\000\138\000\000\000\138\000\136\002B\004$\000\000\000\000\000\000\000\\\000\000\000\000\000\000\000e\000\000\000\000\001\214\000\000\000\000\001\182\001\205\000m\000\000\000m\000m\000\139\000\000\000\139\002I\000\140\001\184\000\140\002J\000\000\001\185\000o\001\215\000o\000o\002B\004&\001\216\001\198\000\000\000\000\001\217\000\000\002O\000\000\000\000\001\218\002P\000\\\000^\000\000\001\199\000e\000\000\000_\001\198\001\001\000\000\000`\002I\000\000\001\184\000\000\000\000\002R\001\185\000\000\000\000\001\199\001\026\001\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002T\000\000\000\000\000i\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\001\214\000\000\000\\\000`\000\000\000\000\000e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\240\000\000\000\000\002J\000\000\000\\\001\215\000\000\000\000\000e\000\000\001\216\000\000\001\198\000i\001\217\000^\000\000\002O\000\000\001\218\000_\002P\000\000\000\000\000`\001\199\000\000\000\000\000\000\000\000\000\000\000^\000\211\000\000\000\236\002'\000_\002J\002R\000\000\000`\000\000\000\000\000\000\000\000\000\000\000\000\001\198\000^\000i\000j\002)\002O\000_\002T\000\000\002P\000`\000\000\000\000\001\199\000\000\000\000\000\000\000\000\000i\000\000\000\000\002+\000\137\000\000\000\000\001\214\002R\000k\000\000\000^\000\\\000\000\000\213\000\000\000e\000i\000\214\000\000\000\000\000\000\000\000\000\000\002T\000\000\000\000\001\215\000j\000\\\000\000\000\000\001\216\000e\000\138\000\000\001\217\000\000\000\000\000\000\000\000\001\218\001\214\000\000\000\000\000\227\000\000\000\137\000\000\000\000\000\000\000\000\000k\000\000\000\000\000m\000^\000\000\000\000\000\139\000\000\000_\001\215\000\140\000j\000`\000\000\001\216\000\000\000o\000\000\001\217\000\000\000^\000\000\000\000\001\218\000\138\000_\000\000\000j\000\000\000`\000\137\000\000\000\000\000\000\000\000\000k\002}\000i\000\000\002\150\000\000\000\000\000\000\000\000\000j\000m\000\137\000\000\000\000\000\139\000\000\000k\000\000\000\140\000i\002}\000\000\000\000\002\150\000o\000\138\000\000\000\000\000\137\000\000\000\000\000\\\000\000\000k\000\000\000e\000\000\000\228\000\000\000\000\000\000\000\138\000\000\000\000\000\000\000^\000m\000\\\000\000\002\127\000\139\000e\000\000\002\128\000\140\000\000\000\000\000\000\000\138\000\000\000o\000\000\000m\000\\\000^\000\000\000\139\000e\002\127\000\000\000\140\000\000\002\128\002\241\000\000\000^\000o\000\000\000\000\000m\000_\000\000\000j\000\139\000`\000\000\000\000\000\140\000\000\000\000\002\253\000^\000\000\000o\000\\\000\000\000_\000\000\000e\000j\000`\002\164\000\000\000\000\000\000\001\001\000k\000^\000\000\000i\000\000\000\000\000_\000\000\000\000\000\000\000`\000\000\002\164\001\018\000\000\000\000\000\000\000k\000\000\000i\000\000\000\000\000\000\000\000\000\000\000\138\000\\\000\000\000\000\000\000\000e\000\000\000^\000\000\000\000\000i\000\000\000_\000\000\000\000\002\141\000`\000\138\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\000\000\\\002\142\000\140\000\000\000e\000\000\000\000\002\141\000o\000\000\000\000\000m\000\\\000\000\000i\000\139\000e\000\000\000^\000\140\002\142\000\000\003\005\000_\000\000\000o\000\000\000`\000\000\000\000\000\000\000j\000\000\000\000\000\000\000\000\000\000\000\000\003\018\000\000\000\000\000\000\000\000\000\000\000^\000\000\000\000\000j\000\000\000_\002\164\000\000\000i\000`\003!\000k\000^\000\000\000\000\000\000\000\000\000_\000\000\000j\000\000\000`\002\164\000\000\000\000\000\000\002\172\000k\000\000\000\000\000\000\000\\\000\000\000\000\000i\000e\000\138\000\000\002\164\000\000\002\197\0038\000\000\000k\000\000\002\172\000i\000\000\000\000\000\000\000j\000\000\000\138\000\000\000\000\000\000\000\000\000m\000\000\002\199\000\000\000\139\000\\\000\000\000\000\000\140\000e\000\000\000\138\002\164\000\000\000o\000\000\000m\000k\000^\000\000\000\139\000\\\003@\000_\000\140\000e\000\000\000`\000\000\000\000\000o\000j\000m\000\000\000\000\000\000\000\139\000\000\000\000\000\000\000\140\000\\\000\138\000\\\000\000\000e\000o\000e\003\170\000^\002\164\000\000\000i\000\000\000_\000k\000\000\000j\000`\000\000\003\182\000\000\000\000\000m\000\000\000^\000\000\000\139\000\000\000j\000_\000\140\000\000\000\000\000`\000\000\002\164\000o\000\000\000\000\000\138\000k\000\000\000i\000\000\000^\000\000\000^\002\164\000\000\000_\000\000\000_\000k\000`\000\000\000`\000\000\000\000\000i\000\000\000m\000\000\000\000\000\000\000\139\000\138\000\000\000\000\000\140\000\000\000\000\000\000\000\000\000\000\000o\000\\\000\000\000\138\000i\000e\000i\000\000\003\188\000\000\000\000\000\000\000m\000\000\000-\000\000\000\139\000j\000\000\000\000\000\140\000\\\000\000\000\000\000m\000e\000o\000\000\000\139\000\211\000\000\000\238\000\140\000\000\005\015\000\000\002\164\000\000\000o\003\195\000\000\000k\000\000\000\000\000\000\000^\000\000\000\000\000j\000\\\000_\000\000\000\000\000e\000`\003\204\000\000\000\000\000\000\005\020\000\000\000\000\005v\000\000\000j\000^\000\138\002\164\001U\000\000\000_\000\000\000k\000^\000`\003\218\000\213\003\232\000\000\000i\000\214\000\000\001O\002\164\000j\000\000\000j\000m\000k\000\000\000\000\000\139\000\000\000^\000\000\000\140\000\\\000\138\000_\000i\000e\000o\000`\002\164\000\000\002\164\000\000\000\227\000k\000\000\000k\000\000\000\000\000\138\000\000\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\000\000\000\000\000\000\140\000i\000\000\000\000\000\000\000\000\000o\000\138\000m\000\138\000\000\000\\\000\139\000\000\000^\000e\000\140\000\000\000\000\000_\000\000\000\000\000o\000`\003\239\000\000\000\000\000\000\000m\001@\000m\000\000\000\139\000j\000\139\000\000\000\140\000\000\000\140\000\000\000\000\001P\000o\000\000\000o\000\000\000\000\000\000\000i\000\000\000\000\000\000\002\164\000j\000\000\000^\000\000\000k\000\000\000\000\000_\000\228\000\000\000\000\000`\000\000\000\000\000\000\001[\000\000\003\178\000\000\005\028\001X\000\000\000\160\001Y\000k\000\166\000\000\000\000\000j\000\138\000\000\000\000\000\000\000\000\005\021\000\000\000i\000\000\000\000\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\005\028\000\000\000\138\000m\000\\\000k\000\000\000\139\000e\001\000\000\000\000\140\000\000\000\000\000\000\000\000\000\000\000o\000\000\005\024\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000j\001\001\000\138\000\140\000\000\000\000\001\002\000\000\000^\000o\001\003\000\000\000\000\000_\000\000\001\004\000\000\000`\000\000\0010\000^\000\000\000\000\000m\000k\000_\000\000\000\139\000\\\000`\000\000\000\140\000e\000\000\000\000\000\000\000\000\000o\000\000\000\\\000\000\000j\000i\000e\000\000\000\000\000\000\000\000\000\000\000\138\000\000\000\\\000\000\000\000\000i\000e\000\000\000\000\000\000\000\000\000\175\000\000\000\000\000\000\000\000\000k\000\000\000\000\000\000\000\000\000m\000\000\000^\000\000\000\139\000\000\000\000\000_\000\140\000\000\000\000\000`\000\000\000^\000o\000\000\000\000\000\000\000_\000\000\000\138\000\000\000`\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\000\000\000\000\000\\\000`\000\000\000i\000e\000\000\000\000\000\211\000m\000\236\000\000\000\000\000\139\000\000\000i\000\000\000\140\000\\\000\000\000j\000\000\000e\000o\000\000\000\000\000\000\000i\000\000\000\000\000\000\000\000\000j\000\000\000\\\000\000\000\000\000\000\000e\000\190\000\000\000\000\000\000\000\000\000k\000^\000\000\000\000\000\000\000\000\000_\000\221\000^\000\000\000`\000\213\000k\000\000\000\000\000\214\000\000\000\000\000^\000\000\000\000\000\000\000\000\000_\000\000\000\138\000\000\000`\000\000\000\211\000\211\000\236\000\238\000\000\000^\000i\000\000\000\138\000\000\000_\000j\000\000\000\227\000`\000\000\000\000\000m\000\000\000\000\000\000\000\139\000j\000i\000\\\000\140\000\000\000\000\000e\000m\000\250\000o\000\000\000\139\000j\000k\000\000\000\140\000\000\000i\000\000\001\152\000\000\000o\000^\000^\000k\000\213\000\213\000\000\000\000\000\214\000\214\001\156\000\000\000\000\000\000\000\000\000k\000\000\000\138\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000^\000\000\000\000\000\138\000\\\000_\000\000\000\000\000e\000`\000\227\000\227\000\000\000m\000\000\000\138\000\000\000\139\000j\000\\\000\000\000\140\000\000\000e\000m\000\228\000\000\000o\000\139\000\000\000\000\000\000\000\140\000\000\000i\000j\000m\001\192\000o\000\000\000\139\000\000\000k\000\000\000\140\000\\\000\000\000\000\000^\000e\000o\000j\000\000\000_\001\255\000\000\000\000\000`\000\000\000k\000\000\000\000\000\\\000^\000\000\000\000\000e\000\138\000_\000\000\002\004\000\000\000`\000\000\000\000\000k\000\000\000\000\000\000\000\000\000\000\000\000\000i\000\000\000\138\000\000\000\000\000\000\000m\000^\000\228\000\228\000\139\001\001\000_\000\000\000\140\000i\000`\000\000\000\138\000\000\000o\000\000\000\000\000m\000^\001\020\000\000\000\139\000\000\000_\000\000\000\140\000j\000`\000\000\004;\000\000\000o\000\000\000m\000\000\000i\000\000\000\139\000\\\000\000\000\000\000\140\000e\000\000\000\000\002\008\000\000\000o\000\000\000\000\000k\001\000\000i\000\\\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\000\000\000\000\000\000\000e\001\001\001\001\000\000\000\000\000j\000\138\001\002\000\000\000\000\000\000\001\003\000\000\000^\000\000\001\022\001\004\000\000\000_\000\000\000j\000\000\000`\000\000\002\031\000\000\000\000\000m\000^\000k\000\000\000\139\000\\\000_\000\000\000\140\000g\000`\000\000\002F\000^\000o\000\000\000\000\000k\000_\000j\000i\000\\\000`\000\000\000\000\000g\000\000\000\138\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000i\000j\000\000\002\135\000\000\000\000\000\000\000\138\000k\000\000\000\000\000\000\000i\000m\000^\000\000\000\000\000\139\000\000\000_\002\153\000\140\000\000\000`\000\000\000k\000\000\000o\000m\000\000\000^\000\000\000\139\000\138\000\\\000_\000\140\000\000\000g\000`\000\000\000\000\000o\000\000\000\000\000\000\000\000\000\\\000i\000\\\000\138\000g\000\000\000g\000m\000-\000\000\000\000\000\139\000\000\000\000\000\000\000\140\000\000\000i\000j\000\000\000\000\000o\000\\\000\000\000m\000\000\000q\000\000\000\139\000\000\000\000\000^\000\140\000j\000\000\000\000\000_\002\155\000o\000\000\000`\000\000\000k\000\000\000^\000j\000^\000\000\000\000\000_\000\000\000_\003\158\000`\000\000\000`\000\000\000k\000\000\000\000\000\000\000\000\001U\000\000\004\006\000i\000^\000\138\000\000\000k\000\000\000_\000\000\000\000\000\000\000`\001O\000\000\000i\000\000\000i\000j\000\138\000\000\000\000\000\000\000\000\000\000\000m\000\000\000\000\000\000\000\139\000\000\000\138\000\\\000\140\000j\000\000\000q\000i\000\000\000o\000m\000\000\000k\000\000\000\139\000\000\000\000\000\000\000\140\000\000\000\000\000\000\000m\000\000\000o\000\000\000\139\000\000\000k\000\\\000\140\000\000\000\000\000q\000\000\000\000\000o\000l\000\000\000\000\000\000\000\\\000\000\000\000\000\000\000q\000^\000\000\000\000\000\000\000\000\000_\000j\000l\000\000\000`\001@\000\000\000m\000\000\000\\\000\000\000\000\000\151\000q\000j\000\000\000j\001P\000\000\000\000\000\000\000o\000^\000m\000\000\000k\000\\\000_\000\240\000i\000q\000`\000\000\000\000\000^\000\000\000j\000o\000k\000_\000k\000\000\000\000\000`\001[\000\000\003\214\000\000\000\000\001X\000l\000\160\001Y\000^\000\166\000\000\000i\000\000\000_\000\000\000k\000\000\000`\000l\000\211\000l\000\236\000\000\000i\000\000\000^\000m\000\211\000\\\000\236\000_\000\242\000q\000\000\000`\000\211\000\000\000\236\000\000\000m\000o\000m\000i\000\\\001\207\000\\\001\209\000q\000\000\000q\000\000\000\000\000\000\000o\000\000\000o\000\000\000\000\000\\\000i\000\000\000m\000q\000^\000j\000\000\000\213\000\000\001\182\001\203\000\214\000^\000^\000\000\000\213\000v\000\\\000_\000\214\000^\000q\000`\000\213\000\000\000\000\000\000\000\214\000^\000k\000^\000\000\000j\000_\000\211\000_\000\236\000`\000\227\000`\001\182\001\203\000\000\000^\000j\000\000\000\227\000i\000_\000\000\000\000\000\000\000`\000^\000\227\001\184\000k\000\000\000\000\001\185\000\000\000^\000i\000j\000i\000\000\000_\000\000\000k\000\000\000`\000\000\000\000\001\182\001\203\000m\000\000\000i\000^\000\000\000j\000\213\000\000\000\000\000^\000\214\001\184\000k\000\000\000x\001\185\001\182\001\203\000\000\000\000\000i\000\000\000\000\000\000\001\182\001\203\000\000\000m\000\000\000k\000\000\000\000\000\000\000\000\001\182\001\203\000\000\000\227\000\000\000m\000\000\000z\000^\000\228\001\184\000\000\000\000\000\000\001\185\000\000\000\000\000\228\000j\000|\000\000\001\182\001\203\000\000\000m\000\228\000^\000\000\001\184\000\000\000\000\000\000\001\185\000j\000^\000j\001\184\000\000\000~\000\000\001\185\000m\000k\000\000\000^\001\198\001\184\000\000\000j\000\000\001\185\000\000\000\000\000\000\000\000\000\128\000\000\000k\001\199\000k\000\000\000\000\000\000\000\000\000\000\000^\000j\001\184\000\000\000\000\000\000\001\185\000k\000\000\000\000\000\000\001\198\001\001\000\000\000\000\000\000\000\000\000\000\000\228\000\000\001\001\000\000\000\000\000m\001\199\000k\001\024\000\000\001\001\000\000\000\000\000\000\000\000\000\000\001\030\000\000\000\000\000\130\000m\000\000\000m\000\000\001 \000\000\001\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000m\000\142\000\000\000\000\001\199\000\000\000\000\001\215\000\000\001\198\000\000\000\000\000\000\000\000\000\144\000\000\000\000\001\198\000m\000\000\000\000\001\232\001\199\000\000\000\000\000\000\000\000\001\198\000\000\000\000\001\199\000\000\000\146\001\001\000\000\000\000\000\000\000\000\001\215\000\000\001\199\000\000\000\000\000\000\000\000\000\000\000\000\001\"\001\198\000\000\000\000\000\000\001\234\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\199\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\215\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\236\000\000\000\000\000\000\001\215\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\215\000\000\000\000\000\000\000\000\000\000\001\238\000\000\000\000\000\000\001\215\000\000\000\000\000\000\001\244\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\246\000\000\000\000\000\000\000\000\000\000\000\000\001\215\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\248"))
let semantic_action =
[|
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_aexpr =
-# 1656 "parser_cocci_menhir.mly"
+# 1662 "parser_cocci_menhir.mly"
( Ast0.set_arg_exp _1 )
-# 1465 "parser_cocci_menhir.ml"
+# 1497 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 65 "parser_cocci_menhir.mly"
(Parse_aux.list_info)
-# 1486 "parser_cocci_menhir.ml"
+# 1518 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_aexpr =
-# 1658 "parser_cocci_menhir.mly"
+# 1664 "parser_cocci_menhir.mly"
( let (nm,lenname,pure,clt) = _1 in
let nm = P.clt2mcode nm clt in
let lenname =
Some nm -> Some(P.clt2mcode nm clt)
| None -> None in
Ast0.wrap(Ast0.MetaExprList(nm,lenname,pure)) )
-# 1499 "parser_cocci_menhir.ml"
+# 1531 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_aexpr =
-# 1666 "parser_cocci_menhir.mly"
+# 1672 "parser_cocci_menhir.mly"
( Ast0.set_arg_exp(Ast0.wrap(Ast0.TypeExp(_1))) )
-# 1523 "parser_cocci_menhir.ml"
+# 1555 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_any_strict =
-# 1712 "parser_cocci_menhir.mly"
+# 1716 "parser_cocci_menhir.mly"
( Ast.WhenAny )
-# 1545 "parser_cocci_menhir.ml"
+# 1577 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_any_strict =
-# 1713 "parser_cocci_menhir.mly"
+# 1717 "parser_cocci_menhir.mly"
( Ast.WhenStrict )
-# 1567 "parser_cocci_menhir.ml"
+# 1599 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_any_strict =
-# 1714 "parser_cocci_menhir.mly"
+# 1718 "parser_cocci_menhir.mly"
( Ast.WhenForall )
-# 1589 "parser_cocci_menhir.ml"
+# 1621 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_any_strict =
-# 1715 "parser_cocci_menhir.mly"
+# 1719 "parser_cocci_menhir.mly"
( Ast.WhenExists )
-# 1611 "parser_cocci_menhir.ml"
+# 1643 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1190 "parser_cocci_menhir.mly"
( _1 )
-# 1635 "parser_cocci_menhir.ml"
+# 1667 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 1667 "parser_cocci_menhir.ml"
+# 1699 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1192 "parser_cocci_menhir.mly"
( P.arith_op Ast.Mul _1 _2 _3 )
-# 1675 "parser_cocci_menhir.ml"
+# 1707 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 96 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 1707 "parser_cocci_menhir.ml"
+# 1739 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1194 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 1715 "parser_cocci_menhir.ml"
+# 1747 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 1747 "parser_cocci_menhir.ml"
+# 1779 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1196 "parser_cocci_menhir.mly"
( P.arith_op Ast.Plus _1 _2 _3 )
-# 1755 "parser_cocci_menhir.ml"
+# 1787 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 1787 "parser_cocci_menhir.ml"
+# 1819 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1198 "parser_cocci_menhir.mly"
( P.arith_op Ast.Minus _1 _2 _3 )
-# 1795 "parser_cocci_menhir.ml"
+# 1827 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 95 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 1827 "parser_cocci_menhir.ml"
+# 1859 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1200 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 1835 "parser_cocci_menhir.ml"
+# 1867 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 94 "parser_cocci_menhir.mly"
(Ast_cocci.logicalOp * Data.clt)
-# 1867 "parser_cocci_menhir.ml"
+# 1899 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1202 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.logic_op op _1 clt _3 )
-# 1875 "parser_cocci_menhir.ml"
+# 1907 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 1907 "parser_cocci_menhir.ml"
+# 1939 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1204 "parser_cocci_menhir.mly"
( P.logic_op Ast.Eq _1 _2 _3 )
-# 1915 "parser_cocci_menhir.ml"
+# 1947 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 1947 "parser_cocci_menhir.ml"
+# 1979 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1206 "parser_cocci_menhir.mly"
( P.logic_op Ast.NotEq _1 _2 _3 )
-# 1955 "parser_cocci_menhir.ml"
+# 1987 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 92 "parser_cocci_menhir.mly"
(Data.clt)
-# 1987 "parser_cocci_menhir.ml"
+# 2019 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1208 "parser_cocci_menhir.mly"
( P.arith_op Ast.And _1 _2 _3 )
-# 1995 "parser_cocci_menhir.ml"
+# 2027 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 90 "parser_cocci_menhir.mly"
(Data.clt)
-# 2027 "parser_cocci_menhir.ml"
+# 2059 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1210 "parser_cocci_menhir.mly"
( P.arith_op Ast.Or _1 _2 _3 )
-# 2035 "parser_cocci_menhir.ml"
+# 2067 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 91 "parser_cocci_menhir.mly"
(Data.clt)
-# 2067 "parser_cocci_menhir.ml"
+# 2099 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1212 "parser_cocci_menhir.mly"
( P.arith_op Ast.Xor _1 _2 _3 )
-# 2075 "parser_cocci_menhir.ml"
+# 2107 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 89 "parser_cocci_menhir.mly"
(Data.clt)
-# 2107 "parser_cocci_menhir.ml"
+# 2139 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1214 "parser_cocci_menhir.mly"
( P.logic_op Ast.AndLog _1 _2 _3 )
-# 2115 "parser_cocci_menhir.ml"
+# 2147 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 88 "parser_cocci_menhir.mly"
(Data.clt)
-# 2147 "parser_cocci_menhir.ml"
+# 2179 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_dot_expressions_ =
# 1216 "parser_cocci_menhir.mly"
( P.logic_op Ast.OrLog _1 _2 _3 )
-# 2155 "parser_cocci_menhir.ml"
+# 2187 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1190 "parser_cocci_menhir.mly"
( _1 )
-# 2179 "parser_cocci_menhir.ml"
+# 2211 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 2211 "parser_cocci_menhir.ml"
+# 2243 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1192 "parser_cocci_menhir.mly"
( P.arith_op Ast.Mul _1 _2 _3 )
-# 2219 "parser_cocci_menhir.ml"
+# 2251 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 96 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 2251 "parser_cocci_menhir.ml"
+# 2283 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1194 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 2259 "parser_cocci_menhir.ml"
+# 2291 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 2291 "parser_cocci_menhir.ml"
+# 2323 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1196 "parser_cocci_menhir.mly"
( P.arith_op Ast.Plus _1 _2 _3 )
-# 2299 "parser_cocci_menhir.ml"
+# 2331 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 2331 "parser_cocci_menhir.ml"
+# 2363 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1198 "parser_cocci_menhir.mly"
( P.arith_op Ast.Minus _1 _2 _3 )
-# 2339 "parser_cocci_menhir.ml"
+# 2371 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 95 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 2371 "parser_cocci_menhir.ml"
+# 2403 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1200 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 2379 "parser_cocci_menhir.ml"
+# 2411 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 94 "parser_cocci_menhir.mly"
(Ast_cocci.logicalOp * Data.clt)
-# 2411 "parser_cocci_menhir.ml"
+# 2443 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1202 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.logic_op op _1 clt _3 )
-# 2419 "parser_cocci_menhir.ml"
+# 2451 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 2451 "parser_cocci_menhir.ml"
+# 2483 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1204 "parser_cocci_menhir.mly"
( P.logic_op Ast.Eq _1 _2 _3 )
-# 2459 "parser_cocci_menhir.ml"
+# 2491 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 2491 "parser_cocci_menhir.ml"
+# 2523 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1206 "parser_cocci_menhir.mly"
( P.logic_op Ast.NotEq _1 _2 _3 )
-# 2499 "parser_cocci_menhir.ml"
+# 2531 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 92 "parser_cocci_menhir.mly"
(Data.clt)
-# 2531 "parser_cocci_menhir.ml"
+# 2563 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1208 "parser_cocci_menhir.mly"
( P.arith_op Ast.And _1 _2 _3 )
-# 2539 "parser_cocci_menhir.ml"
+# 2571 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 90 "parser_cocci_menhir.mly"
(Data.clt)
-# 2571 "parser_cocci_menhir.ml"
+# 2603 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1210 "parser_cocci_menhir.mly"
( P.arith_op Ast.Or _1 _2 _3 )
-# 2579 "parser_cocci_menhir.ml"
+# 2611 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 91 "parser_cocci_menhir.mly"
(Data.clt)
-# 2611 "parser_cocci_menhir.ml"
+# 2643 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1212 "parser_cocci_menhir.mly"
( P.arith_op Ast.Xor _1 _2 _3 )
-# 2619 "parser_cocci_menhir.ml"
+# 2651 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 89 "parser_cocci_menhir.mly"
(Data.clt)
-# 2651 "parser_cocci_menhir.ml"
+# 2683 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1214 "parser_cocci_menhir.mly"
( P.logic_op Ast.AndLog _1 _2 _3 )
-# 2659 "parser_cocci_menhir.ml"
+# 2691 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 88 "parser_cocci_menhir.mly"
(Data.clt)
-# 2691 "parser_cocci_menhir.ml"
+# 2723 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_invalid_ =
# 1216 "parser_cocci_menhir.mly"
( P.logic_op Ast.OrLog _1 _2 _3 )
-# 2699 "parser_cocci_menhir.ml"
+# 2731 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1190 "parser_cocci_menhir.mly"
( _1 )
-# 2723 "parser_cocci_menhir.ml"
+# 2755 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 2755 "parser_cocci_menhir.ml"
+# 2787 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1192 "parser_cocci_menhir.mly"
( P.arith_op Ast.Mul _1 _2 _3 )
-# 2763 "parser_cocci_menhir.ml"
+# 2795 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 96 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 2795 "parser_cocci_menhir.ml"
+# 2827 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1194 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 2803 "parser_cocci_menhir.ml"
+# 2835 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 2835 "parser_cocci_menhir.ml"
+# 2867 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1196 "parser_cocci_menhir.mly"
( P.arith_op Ast.Plus _1 _2 _3 )
-# 2843 "parser_cocci_menhir.ml"
+# 2875 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 2875 "parser_cocci_menhir.ml"
+# 2907 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1198 "parser_cocci_menhir.mly"
( P.arith_op Ast.Minus _1 _2 _3 )
-# 2883 "parser_cocci_menhir.ml"
+# 2915 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 95 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 2915 "parser_cocci_menhir.ml"
+# 2947 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1200 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 2923 "parser_cocci_menhir.ml"
+# 2955 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 94 "parser_cocci_menhir.mly"
(Ast_cocci.logicalOp * Data.clt)
-# 2955 "parser_cocci_menhir.ml"
+# 2987 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1202 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.logic_op op _1 clt _3 )
-# 2963 "parser_cocci_menhir.ml"
+# 2995 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 2995 "parser_cocci_menhir.ml"
+# 3027 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1204 "parser_cocci_menhir.mly"
( P.logic_op Ast.Eq _1 _2 _3 )
-# 3003 "parser_cocci_menhir.ml"
+# 3035 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 3035 "parser_cocci_menhir.ml"
+# 3067 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1206 "parser_cocci_menhir.mly"
( P.logic_op Ast.NotEq _1 _2 _3 )
-# 3043 "parser_cocci_menhir.ml"
+# 3075 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 92 "parser_cocci_menhir.mly"
(Data.clt)
-# 3075 "parser_cocci_menhir.ml"
+# 3107 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1208 "parser_cocci_menhir.mly"
( P.arith_op Ast.And _1 _2 _3 )
-# 3083 "parser_cocci_menhir.ml"
+# 3115 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 90 "parser_cocci_menhir.mly"
(Data.clt)
-# 3115 "parser_cocci_menhir.ml"
+# 3147 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1210 "parser_cocci_menhir.mly"
( P.arith_op Ast.Or _1 _2 _3 )
-# 3123 "parser_cocci_menhir.ml"
+# 3155 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 91 "parser_cocci_menhir.mly"
(Data.clt)
-# 3155 "parser_cocci_menhir.ml"
+# 3187 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1212 "parser_cocci_menhir.mly"
( P.arith_op Ast.Xor _1 _2 _3 )
-# 3163 "parser_cocci_menhir.ml"
+# 3195 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 89 "parser_cocci_menhir.mly"
(Data.clt)
-# 3195 "parser_cocci_menhir.ml"
+# 3227 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1214 "parser_cocci_menhir.mly"
( P.logic_op Ast.AndLog _1 _2 _3 )
-# 3203 "parser_cocci_menhir.ml"
+# 3235 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 88 "parser_cocci_menhir.mly"
(Data.clt)
-# 3235 "parser_cocci_menhir.ml"
+# 3267 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_eexpr_nest_expressions_ =
# 1216 "parser_cocci_menhir.mly"
( P.logic_op Ast.OrLog _1 _2 _3 )
-# 3243 "parser_cocci_menhir.ml"
+# 3275 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arith_expr_expr_invalid_ =
# 1190 "parser_cocci_menhir.mly"
( _1 )
-# 3267 "parser_cocci_menhir.ml"
+# 3299 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 3299 "parser_cocci_menhir.ml"
+# 3331 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1192 "parser_cocci_menhir.mly"
( P.arith_op Ast.Mul _1 _2 _3 )
-# 3307 "parser_cocci_menhir.ml"
+# 3339 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 96 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 3339 "parser_cocci_menhir.ml"
+# 3371 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1194 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 3347 "parser_cocci_menhir.ml"
+# 3379 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 3379 "parser_cocci_menhir.ml"
+# 3411 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1196 "parser_cocci_menhir.mly"
( P.arith_op Ast.Plus _1 _2 _3 )
-# 3387 "parser_cocci_menhir.ml"
+# 3419 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 3419 "parser_cocci_menhir.ml"
+# 3451 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1198 "parser_cocci_menhir.mly"
( P.arith_op Ast.Minus _1 _2 _3 )
-# 3427 "parser_cocci_menhir.ml"
+# 3459 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 95 "parser_cocci_menhir.mly"
(Ast_cocci.arithOp * Data.clt)
-# 3459 "parser_cocci_menhir.ml"
+# 3491 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1200 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.arith_op op _1 clt _3 )
-# 3467 "parser_cocci_menhir.ml"
+# 3499 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 94 "parser_cocci_menhir.mly"
(Ast_cocci.logicalOp * Data.clt)
-# 3499 "parser_cocci_menhir.ml"
+# 3531 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1202 "parser_cocci_menhir.mly"
( let (op,clt) = _2 in P.logic_op op _1 clt _3 )
-# 3507 "parser_cocci_menhir.ml"
+# 3539 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 3539 "parser_cocci_menhir.ml"
+# 3571 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1204 "parser_cocci_menhir.mly"
( P.logic_op Ast.Eq _1 _2 _3 )
-# 3547 "parser_cocci_menhir.ml"
+# 3579 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 93 "parser_cocci_menhir.mly"
(Data.clt)
-# 3579 "parser_cocci_menhir.ml"
+# 3611 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1206 "parser_cocci_menhir.mly"
( P.logic_op Ast.NotEq _1 _2 _3 )
-# 3587 "parser_cocci_menhir.ml"
+# 3619 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 92 "parser_cocci_menhir.mly"
(Data.clt)
-# 3619 "parser_cocci_menhir.ml"
+# 3651 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1208 "parser_cocci_menhir.mly"
( P.arith_op Ast.And _1 _2 _3 )
-# 3627 "parser_cocci_menhir.ml"
+# 3659 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 90 "parser_cocci_menhir.mly"
(Data.clt)
-# 3659 "parser_cocci_menhir.ml"
+# 3691 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1210 "parser_cocci_menhir.mly"
( P.arith_op Ast.Or _1 _2 _3 )
-# 3667 "parser_cocci_menhir.ml"
+# 3699 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 91 "parser_cocci_menhir.mly"
(Data.clt)
-# 3699 "parser_cocci_menhir.ml"
+# 3731 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1212 "parser_cocci_menhir.mly"
( P.arith_op Ast.Xor _1 _2 _3 )
-# 3707 "parser_cocci_menhir.ml"
+# 3739 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 89 "parser_cocci_menhir.mly"
(Data.clt)
-# 3739 "parser_cocci_menhir.ml"
+# 3771 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1214 "parser_cocci_menhir.mly"
( P.logic_op Ast.AndLog _1 _2 _3 )
-# 3747 "parser_cocci_menhir.ml"
+# 3779 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 88 "parser_cocci_menhir.mly"
(Data.clt)
-# 3779 "parser_cocci_menhir.ml"
+# 3811 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_arith_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_arith_expr_expr_invalid_ =
# 1216 "parser_cocci_menhir.mly"
( P.logic_op Ast.OrLog _1 _2 _3 )
-# 3787 "parser_cocci_menhir.ml"
+# 3819 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arity =
# 435 "parser_cocci_menhir.mly"
( Ast.UNIQUE )
-# 3809 "parser_cocci_menhir.ml"
+# 3841 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arity =
# 436 "parser_cocci_menhir.mly"
( Ast.OPT )
-# 3831 "parser_cocci_menhir.ml"
+# 3863 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arity =
# 437 "parser_cocci_menhir.mly"
( Ast.MULTI )
-# 3853 "parser_cocci_menhir.ml"
+# 3885 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_arity =
# 438 "parser_cocci_menhir.mly"
( Ast.NONE )
-# 3870 "parser_cocci_menhir.ml"
+# 3902 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let r : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 3901 "parser_cocci_menhir.ml"
+# 3933 "parser_cocci_menhir.ml"
) = Obj.magic r in
let i : 'tv_option_eexpr_ = Obj.magic i in
let l : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 3907 "parser_cocci_menhir.ml"
+# 3939 "parser_cocci_menhir.ml"
) = Obj.magic l in
let _startpos = _startpos_l_ in
let _endpos = _endpos_r_ in
let _v : 'tv_array_dec =
# 1004 "parser_cocci_menhir.mly"
( (l,i,r) )
-# 3914 "parser_cocci_menhir.ml"
+# 3946 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_assign_expr_eexpr_dot_expressions_ =
# 1162 "parser_cocci_menhir.mly"
( _1 )
-# 3938 "parser_cocci_menhir.ml"
+# 3970 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 107 "parser_cocci_menhir.mly"
(Ast_cocci.assignOp * Data.clt)
-# 3970 "parser_cocci_menhir.ml"
+# 4002 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( let (op,clt) = _2 in
Ast0.wrap(Ast0.Assignment(_1,P.clt2mcode op clt,
Ast0.set_arg_exp _3,false)) )
-# 3980 "parser_cocci_menhir.ml"
+# 4012 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4012 "parser_cocci_menhir.ml"
+# 4044 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap
(Ast0.Assignment
(_1,P.clt2mcode Ast.SimpleAssign _2,Ast0.set_arg_exp _3,false)) )
-# 4022 "parser_cocci_menhir.ml"
+# 4054 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_assign_expr_eexpr_nest_expressions_ =
# 1162 "parser_cocci_menhir.mly"
( _1 )
-# 4046 "parser_cocci_menhir.ml"
+# 4078 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 107 "parser_cocci_menhir.mly"
(Ast_cocci.assignOp * Data.clt)
-# 4078 "parser_cocci_menhir.ml"
+# 4110 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( let (op,clt) = _2 in
Ast0.wrap(Ast0.Assignment(_1,P.clt2mcode op clt,
Ast0.set_arg_exp _3,false)) )
-# 4088 "parser_cocci_menhir.ml"
+# 4120 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4120 "parser_cocci_menhir.ml"
+# 4152 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap
(Ast0.Assignment
(_1,P.clt2mcode Ast.SimpleAssign _2,Ast0.set_arg_exp _3,false)) )
-# 4130 "parser_cocci_menhir.ml"
+# 4162 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_assign_expr_expr_invalid_ =
# 1162 "parser_cocci_menhir.mly"
( _1 )
-# 4154 "parser_cocci_menhir.ml"
+# 4186 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 107 "parser_cocci_menhir.mly"
(Ast_cocci.assignOp * Data.clt)
-# 4186 "parser_cocci_menhir.ml"
+# 4218 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( let (op,clt) = _2 in
Ast0.wrap(Ast0.Assignment(_1,P.clt2mcode op clt,
Ast0.set_arg_exp _3,false)) )
-# 4196 "parser_cocci_menhir.ml"
+# 4228 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4228 "parser_cocci_menhir.ml"
+# 4260 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap
(Ast0.Assignment
(_1,P.clt2mcode Ast.SimpleAssign _2,Ast0.set_arg_exp _3,false)) )
-# 4238 "parser_cocci_menhir.ml"
+# 4270 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_assign_expr_bis =
# 1173 "parser_cocci_menhir.mly"
( _1 )
-# 4262 "parser_cocci_menhir.ml"
+# 4294 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 107 "parser_cocci_menhir.mly"
(Ast_cocci.assignOp * Data.clt)
-# 4294 "parser_cocci_menhir.ml"
+# 4326 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( let (op,clt) = _2 in
Ast0.wrap(Ast0.Assignment(_1,P.clt2mcode op clt,
Ast0.set_arg_exp _3,false)) )
-# 4304 "parser_cocci_menhir.ml"
+# 4336 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4336 "parser_cocci_menhir.ml"
+# 4368 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_unary_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap
(Ast0.Assignment
(_1,P.clt2mcode Ast.SimpleAssign _2,Ast0.set_arg_exp _3,false)) )
-# 4346 "parser_cocci_menhir.ml"
+# 4378 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_basic_expr_eexpr_dot_expressions_ =
# 1159 "parser_cocci_menhir.mly"
( _1 )
-# 4370 "parser_cocci_menhir.ml"
+# 4402 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_basic_expr_eexpr_nest_expressions_ =
# 1159 "parser_cocci_menhir.mly"
( _1 )
-# 4394 "parser_cocci_menhir.ml"
+# 4426 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_basic_expr_expr_invalid_ =
# 1159 "parser_cocci_menhir.mly"
( _1 )
-# 4418 "parser_cocci_menhir.ml"
+# 4450 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 4450 "parser_cocci_menhir.ml"
+# 4482 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 4455 "parser_cocci_menhir.ml"
+# 4487 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_case_line =
# 876 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Default(P.clt2mcode "default" _1,P.clt2mcode ":" _2,_3)) )
-# 4462 "parser_cocci_menhir.ml"
+# 4494 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 4499 "parser_cocci_menhir.ml"
+# 4531 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 4505 "parser_cocci_menhir.ml"
+# 4537 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__4_ in
let _v : 'tv_case_line =
# 878 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Case(P.clt2mcode "case" _1,_2,P.clt2mcode ":" _3,_4)) )
-# 4512 "parser_cocci_menhir.ml"
+# 4544 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_cast_expr_eexpr_dot_expressions_ =
# 1219 "parser_cocci_menhir.mly"
( _1 )
-# 4536 "parser_cocci_menhir.ml"
+# 4568 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 4573 "parser_cocci_menhir.ml"
+# 4605 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 4579 "parser_cocci_menhir.ml"
+# 4611 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let _startpos = _startpos_lp_ in
let _endpos = _endpos_e_ in
# 1221 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
P.clt2mcode ")" rp, e)) )
-# 4587 "parser_cocci_menhir.ml"
+# 4619 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_cast_expr_eexpr_invalid_ =
# 1219 "parser_cocci_menhir.mly"
( _1 )
-# 4611 "parser_cocci_menhir.ml"
+# 4643 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 4648 "parser_cocci_menhir.ml"
+# 4680 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 4654 "parser_cocci_menhir.ml"
+# 4686 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let _startpos = _startpos_lp_ in
let _endpos = _endpos_e_ in
# 1221 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
P.clt2mcode ")" rp, e)) )
-# 4662 "parser_cocci_menhir.ml"
+# 4694 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_cast_expr_eexpr_nest_expressions_ =
# 1219 "parser_cocci_menhir.mly"
( _1 )
-# 4686 "parser_cocci_menhir.ml"
+# 4718 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 4723 "parser_cocci_menhir.ml"
+# 4755 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 4729 "parser_cocci_menhir.ml"
+# 4761 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let _startpos = _startpos_lp_ in
let _endpos = _endpos_e_ in
# 1221 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
P.clt2mcode ")" rp, e)) )
-# 4737 "parser_cocci_menhir.ml"
+# 4769 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_cast_expr_expr_invalid_ =
# 1219 "parser_cocci_menhir.mly"
( _1 )
-# 4761 "parser_cocci_menhir.ml"
+# 4793 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 4798 "parser_cocci_menhir.ml"
+# 4830 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 4804 "parser_cocci_menhir.ml"
+# 4836 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let _startpos = _startpos_lp_ in
let _endpos = _endpos_e_ in
# 1221 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Cast (P.clt2mcode "(" lp, t,
P.clt2mcode ")" rp, e)) )
-# 4812 "parser_cocci_menhir.ml"
+# 4844 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_choose_iso =
# 227 "parser_cocci_menhir.mly"
( List.map P.id2name _2 )
-# 4840 "parser_cocci_menhir.ml"
+# 4872 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 4866 "parser_cocci_menhir.ml"
+# 4898 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4871 "parser_cocci_menhir.ml"
+# 4903 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
( function dot_builder ->
[Ast0.wrap(Ast0.PComma(P.clt2mcode "," _1));
dot_builder _2] )
-# 4880 "parser_cocci_menhir.ml"
+# 4912 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4907 "parser_cocci_menhir.ml"
+# 4939 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1474 "parser_cocci_menhir.mly"
( function dot_builder ->
[Ast0.wrap(Ast0.PComma(P.clt2mcode "," _1)); _2] )
-# 4915 "parser_cocci_menhir.ml"
+# 4947 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 4941 "parser_cocci_menhir.ml"
+# 4973 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4946 "parser_cocci_menhir.ml"
+# 4978 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
( function dot_builder ->
[Ast0.wrap(Ast0.PComma(P.clt2mcode "," _1));
dot_builder _2] )
-# 4955 "parser_cocci_menhir.ml"
+# 4987 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 4982 "parser_cocci_menhir.ml"
+# 5014 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1474 "parser_cocci_menhir.mly"
( function dot_builder ->
[Ast0.wrap(Ast0.PComma(P.clt2mcode "," _1)); _2] )
-# 4990 "parser_cocci_menhir.ml"
+# 5022 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_comma_initializers_edots_when_TEllipsis_initialize__ =
# 1051 "parser_cocci_menhir.mly"
( [] )
-# 5007 "parser_cocci_menhir.ml"
+# 5039 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_comma_initializers_edots_when_TEllipsis_initialize__ =
# 1053 "parser_cocci_menhir.mly"
( (function dot_builder -> [dot_builder d])::r )
-# 5037 "parser_cocci_menhir.ml"
+# 5069 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let c : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 5069 "parser_cocci_menhir.ml"
+# 5101 "parser_cocci_menhir.ml"
) = Obj.magic c in
let i : 'tv_initialize2 = Obj.magic i in
let _startpos = _startpos_i_ in
# 1055 "parser_cocci_menhir.mly"
( (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
r )
-# 5078 "parser_cocci_menhir.ml"
+# 5110 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_comma_initializers2_edots_when_TEllipsis_initialize__ =
# 1059 "parser_cocci_menhir.mly"
( [] )
-# 5095 "parser_cocci_menhir.ml"
+# 5127 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let c : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 5127 "parser_cocci_menhir.ml"
+# 5159 "parser_cocci_menhir.ml"
) = Obj.magic c in
let i : 'tv_initialize2 = Obj.magic i in
let _startpos = _startpos_i_ in
# 1061 "parser_cocci_menhir.mly"
( (function dot_builder -> [i; Ast0.wrap(Ast0.IComma(P.clt2mcode "," c))])::
r )
-# 5136 "parser_cocci_menhir.ml"
+# 5168 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_any_strict_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5160 "parser_cocci_menhir.ml"
+# 5192 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_ctype_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5184 "parser_cocci_menhir.ml"
+# 5216 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_d_ident_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5208 "parser_cocci_menhir.ml"
+# 5240 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_dexpr_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5232 "parser_cocci_menhir.ml"
+# 5264 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_ident_or_const_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5256 "parser_cocci_menhir.ml"
+# 5288 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_meta_ident_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5280 "parser_cocci_menhir.ml"
+# 5312 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_pure_ident_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5304 "parser_cocci_menhir.ml"
+# 5336 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_pure_ident_or_meta_ident_ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5328 "parser_cocci_menhir.ml"
+# 5360 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_pure_ident_or_meta_ident_with_not_eq_not_ceq__ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5352 "parser_cocci_menhir.ml"
+# 5384 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_pure_ident_or_meta_ident_with_not_eq_not_eq__ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5376 "parser_cocci_menhir.ml"
+# 5408 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_pure_ident_or_meta_ident_with_not_eq_not_eqe__ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5400 "parser_cocci_menhir.ml"
+# 5432 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_comma_list_pure_ident_or_meta_ident_with_not_eq_not_pos__ =
-# 1688 "parser_cocci_menhir.mly"
+# 1694 "parser_cocci_menhir.mly"
( _1 )
-# 5424 "parser_cocci_menhir.ml"
+# 5456 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_cond_expr_eexpr_dot_expressions_ =
# 1184 "parser_cocci_menhir.mly"
( _1 )
-# 5448 "parser_cocci_menhir.ml"
+# 5480 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let dd : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 5490 "parser_cocci_menhir.ml"
+# 5522 "parser_cocci_menhir.ml"
) = Obj.magic dd in
let t : 'tv_option_eexpr_ = Obj.magic t in
let w : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 5496 "parser_cocci_menhir.ml"
+# 5528 "parser_cocci_menhir.ml"
) = Obj.magic w in
let l : 'tv_arith_expr_eexpr_dot_expressions_ = Obj.magic l in
let _startpos = _startpos_l_ in
# 1186 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
P.clt2mcode ":" dd, r)) )
-# 5505 "parser_cocci_menhir.ml"
+# 5537 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_cond_expr_eexpr_nest_expressions_ =
# 1184 "parser_cocci_menhir.mly"
( _1 )
-# 5529 "parser_cocci_menhir.ml"
+# 5561 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let dd : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 5571 "parser_cocci_menhir.ml"
+# 5603 "parser_cocci_menhir.ml"
) = Obj.magic dd in
let t : 'tv_option_eexpr_ = Obj.magic t in
let w : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 5577 "parser_cocci_menhir.ml"
+# 5609 "parser_cocci_menhir.ml"
) = Obj.magic w in
let l : 'tv_arith_expr_eexpr_nest_expressions_ = Obj.magic l in
let _startpos = _startpos_l_ in
# 1186 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
P.clt2mcode ":" dd, r)) )
-# 5586 "parser_cocci_menhir.ml"
+# 5618 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_cond_expr_expr_invalid_ =
# 1184 "parser_cocci_menhir.mly"
( _1 )
-# 5610 "parser_cocci_menhir.ml"
+# 5642 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let dd : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 5652 "parser_cocci_menhir.ml"
+# 5684 "parser_cocci_menhir.ml"
) = Obj.magic dd in
let t : 'tv_option_eexpr_ = Obj.magic t in
let w : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 5658 "parser_cocci_menhir.ml"
+# 5690 "parser_cocci_menhir.ml"
) = Obj.magic w in
let l : 'tv_arith_expr_expr_invalid_ = Obj.magic l in
let _startpos = _startpos_l_ in
# 1186 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.CondExpr (l, P.clt2mcode "?" w, t,
P.clt2mcode ":" dd, r)) )
-# 5667 "parser_cocci_menhir.ml"
+# 5699 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 54 "parser_cocci_menhir.mly"
(Data.clt)
-# 5688 "parser_cocci_menhir.ml"
+# 5720 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_const_vol =
# 797 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Const _1 )
-# 5695 "parser_cocci_menhir.ml"
+# 5727 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 54 "parser_cocci_menhir.mly"
(Data.clt)
-# 5716 "parser_cocci_menhir.ml"
+# 5748 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_const_vol =
# 798 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Volatile _1 )
-# 5723 "parser_cocci_menhir.ml"
+# 5755 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_continue_struct_decl_list =
# 516 "parser_cocci_menhir.mly"
( [] )
-# 5740 "parser_cocci_menhir.ml"
+# 5772 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_continue_struct_decl_list =
# 517 "parser_cocci_menhir.mly"
( _1@_2 )
-# 5770 "parser_cocci_menhir.ml"
+# 5802 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_continue_struct_decl_list =
# 518 "parser_cocci_menhir.mly"
( _1 )
-# 5794 "parser_cocci_menhir.ml"
+# 5826 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 39 "standard.mly"
( None )
-# 5825 "parser_cocci_menhir.ml"
+# 5857 "parser_cocci_menhir.ml"
in
# 522 "parser_cocci_menhir.mly"
( P.pointerify (P.make_cv cv ty) m )
-# 5831 "parser_cocci_menhir.ml"
+# 5863 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 41 "standard.mly"
( Some x )
-# 5869 "parser_cocci_menhir.ml"
+# 5901 "parser_cocci_menhir.ml"
in
# 522 "parser_cocci_menhir.mly"
( P.pointerify (P.make_cv cv ty) m )
-# 5875 "parser_cocci_menhir.ml"
+# 5907 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let t : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 5902 "parser_cocci_menhir.ml"
+# 5934 "parser_cocci_menhir.ml"
) = Obj.magic t in
let _startpos = _startpos_t_ in
let _endpos = _endpos_m_ in
# 39 "standard.mly"
( None )
-# 5910 "parser_cocci_menhir.ml"
+# 5942 "parser_cocci_menhir.ml"
in
( let ty =
Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
P.pointerify (P.make_cv cv ty) m )
-# 5918 "parser_cocci_menhir.ml"
+# 5950 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let t : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 5950 "parser_cocci_menhir.ml"
+# 5982 "parser_cocci_menhir.ml"
) = Obj.magic t in
let x0 : 'tv_const_vol = Obj.magic x0 in
let _startpos = _startpos_x0_ in
# 41 "standard.mly"
( Some x )
-# 5960 "parser_cocci_menhir.ml"
+# 5992 "parser_cocci_menhir.ml"
in
( let ty =
Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
P.pointerify (P.make_cv cv ty) m )
-# 5968 "parser_cocci_menhir.ml"
+# 6000 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 5999 "parser_cocci_menhir.ml"
+# 6031 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_midzero_list_ctype_ctype_ = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 6005 "parser_cocci_menhir.ml"
+# 6037 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let _startpos = _startpos_lp_ in
let _endpos = _endpos_rp_ in
( let (mids,code) = t in
Ast0.wrap
(Ast0.DisjType(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) )
-# 6014 "parser_cocci_menhir.ml"
+# 6046 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 51 "parser_cocci_menhir.mly"
(Data.clt)
-# 6035 "parser_cocci_menhir.ml"
+# 6067 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_ctype_qualif =
# 542 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Unsigned _1 )
-# 6042 "parser_cocci_menhir.ml"
+# 6074 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 51 "parser_cocci_menhir.mly"
(Data.clt)
-# 6063 "parser_cocci_menhir.ml"
+# 6095 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_ctype_qualif =
# 543 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Signed _1 )
-# 6070 "parser_cocci_menhir.ml"
+# 6102 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
Ast0.wrap
(Ast0.Array(rest,P.clt2mcode "[" l,i,P.clt2mcode "]" r)))
_2 t) )
-# 6107 "parser_cocci_menhir.ml"
+# 6139 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_decl =
# 768 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Param(t, Some i)) )
-# 6137 "parser_cocci_menhir.ml"
+# 6169 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 6193 "parser_cocci_menhir.ml"
+# 6225 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_decl_list_name_opt_decl_ = Obj.magic d in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 6199 "parser_cocci_menhir.ml"
+# 6231 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 6204 "parser_cocci_menhir.ml"
+# 6236 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let i : 'tv_ident = Obj.magic i in
let s : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 6210 "parser_cocci_menhir.ml"
+# 6242 "parser_cocci_menhir.ml"
) = Obj.magic s in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 6215 "parser_cocci_menhir.ml"
+# 6247 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let t : 'tv_fn_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
(t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
Ast0.wrap(Ast0.Param(fnptr, Some i)) )
-# 6228 "parser_cocci_menhir.ml"
+# 6260 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let t : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 6249 "parser_cocci_menhir.ml"
+# 6281 "parser_cocci_menhir.ml"
) = Obj.magic t in
let _startpos = _startpos_t_ in
let _endpos = _endpos_t_ in
# 778 "parser_cocci_menhir.mly"
( let ty = Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)) in
Ast0.wrap(Ast0.VoidParam(ty)) )
-# 6257 "parser_cocci_menhir.ml"
+# 6289 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 6278 "parser_cocci_menhir.ml"
+# 6310 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 781 "parser_cocci_menhir.mly"
( let (nm,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaParam(P.clt2mcode nm clt,pure)) )
-# 6286 "parser_cocci_menhir.ml"
+# 6318 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 6307 "parser_cocci_menhir.ml"
+# 6339 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_decl_ident =
# 1420 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Id(P.id2mcode _1)) )
-# 6314 "parser_cocci_menhir.ml"
+# 6346 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 62 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 6335 "parser_cocci_menhir.ml"
+# 6367 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1422 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) )
-# 6343 "parser_cocci_menhir.ml"
+# 6375 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
if List.exists circle _1
then Ast0.wrap(Ast0.CIRCLES(_1))
else Ast0.wrap(Ast0.DOTS(_1)) )
-# 6371 "parser_cocci_menhir.ml"
+# 6403 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
if List.exists circle _1
then Ast0.wrap(Ast0.CIRCLES(_1))
else Ast0.wrap(Ast0.DOTS(_1)) )
-# 6399 "parser_cocci_menhir.ml"
+# 6431 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_decl_list_start_decl_ =
# 1450 "parser_cocci_menhir.mly"
( [_1] )
-# 6423 "parser_cocci_menhir.ml"
+# 6455 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 6455 "parser_cocci_menhir.ml"
+# 6487 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_one_dec_decl_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_decl_list_start_decl_ =
# 1452 "parser_cocci_menhir.mly"
( _1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," _2))::_3 )
-# 6463 "parser_cocci_menhir.ml"
+# 6495 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 6490 "parser_cocci_menhir.ml"
+# 6522 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1454 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." _1))::
(List.concat(List.map (function x -> x (P.mkpdots "...")) _2)) )
-# 6498 "parser_cocci_menhir.ml"
+# 6530 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_decl_list_start_name_opt_decl_ =
# 1450 "parser_cocci_menhir.mly"
( [_1] )
-# 6522 "parser_cocci_menhir.ml"
+# 6554 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 6554 "parser_cocci_menhir.ml"
+# 6586 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_one_dec_name_opt_decl_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_decl_list_start_name_opt_decl_ =
# 1452 "parser_cocci_menhir.mly"
( _1::Ast0.wrap(Ast0.PComma(P.clt2mcode "," _2))::_3 )
-# 6562 "parser_cocci_menhir.ml"
+# 6594 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 6589 "parser_cocci_menhir.ml"
+# 6621 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1454 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Pdots(P.clt2mcode "..." _1))::
(List.concat(List.map (function x -> x (P.mkpdots "...")) _2)) )
-# 6597 "parser_cocci_menhir.ml"
+# 6629 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 6618 "parser_cocci_menhir.ml"
+# 6650 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1067 "parser_cocci_menhir.mly"
( let (nm,pure,clt) = _1 in
[Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] )
-# 6626 "parser_cocci_menhir.ml"
+# 6658 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
Ast0.wrap
(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
_1 )
-# 6654 "parser_cocci_menhir.ml"
+# 6686 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_decl_statement =
# 1075 "parser_cocci_menhir.mly"
( [_1] )
-# 6678 "parser_cocci_menhir.ml"
+# 6710 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 6709 "parser_cocci_menhir.ml"
+# 6741 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let t : 'tv_midzero_list_fun_start_fun_start_ = Obj.magic t in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 6715 "parser_cocci_menhir.ml"
+# 6747 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
else
[Ast0.wrap(Ast0.Disj(P.clt2mcode "(" _1, code, mids,
P.clt2mcode ")" _3))] )
-# 6730 "parser_cocci_menhir.ml"
+# 6762 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 6751 "parser_cocci_menhir.ml"
+# 6783 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1097 "parser_cocci_menhir.mly"
( let (nm,pure,clt) = _1 in
[Ast0.wrap(Ast0.MetaStmt(P.clt2mcode nm clt,pure))] )
-# 6759 "parser_cocci_menhir.ml"
+# 6791 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
Ast0.wrap
(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),x)))
_1 )
-# 6787 "parser_cocci_menhir.ml"
+# 6819 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_decl_statement_expr =
# 1105 "parser_cocci_menhir.mly"
( [_1] )
-# 6811 "parser_cocci_menhir.ml"
+# 6843 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 6842 "parser_cocci_menhir.ml"
+# 6874 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let t : 'tv_midzero_list_fun_after_stm_fun_after_dots_or_ = Obj.magic t in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 6848 "parser_cocci_menhir.ml"
+# 6880 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
List.map (function x -> Ast0.wrap(Ast0.DOTS x)) code in
[Ast0.wrap(Ast0.Disj(P.clt2mcode "(" _1, dot_code, mids,
P.clt2mcode ")" _3))] )
-# 6862 "parser_cocci_menhir.ml"
+# 6894 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 6888 "parser_cocci_menhir.ml"
+# 6920 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let t : 'tv_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
let _v : 'tv_decl_var =
# 886 "parser_cocci_menhir.mly"
( [Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv))] )
-# 6896 "parser_cocci_menhir.ml"
+# 6928 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 6927 "parser_cocci_menhir.ml"
+# 6959 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_comma_list_d_ident_ = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 39 "standard.mly"
( None )
-# 6937 "parser_cocci_menhir.ml"
+# 6969 "parser_cocci_menhir.ml"
in
(function (id,fn) ->
Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
d )
-# 6946 "parser_cocci_menhir.ml"
+# 6978 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 6982 "parser_cocci_menhir.ml"
+# 7014 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_comma_list_d_ident_ = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 41 "standard.mly"
( Some x )
-# 6994 "parser_cocci_menhir.ml"
+# 7026 "parser_cocci_menhir.ml"
in
(function (id,fn) ->
Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)))
d )
-# 7003 "parser_cocci_menhir.ml"
+# 7035 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_decl_var =
# 892 "parser_cocci_menhir.mly"
( [f] )
-# 7027 "parser_cocci_menhir.ml"
+# 7059 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7068 "parser_cocci_menhir.ml"
+# 7100 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7074 "parser_cocci_menhir.ml"
+# 7106 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 39 "standard.mly"
( None )
-# 7084 "parser_cocci_menhir.ml"
+# 7116 "parser_cocci_menhir.ml"
in
# 894 "parser_cocci_menhir.mly"
(let (id,fn) = d in
[Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))])
-# 7091 "parser_cocci_menhir.ml"
+# 7123 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7137 "parser_cocci_menhir.ml"
+# 7169 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7143 "parser_cocci_menhir.ml"
+# 7175 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 41 "standard.mly"
( Some x )
-# 7155 "parser_cocci_menhir.ml"
+# 7187 "parser_cocci_menhir.ml"
in
# 894 "parser_cocci_menhir.mly"
(let (id,fn) = d in
[Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))])
-# 7162 "parser_cocci_menhir.ml"
+# 7194 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7193 "parser_cocci_menhir.ml"
+# 7225 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_comma_list_d_ident_ = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 7203 "parser_cocci_menhir.ml"
+# 7235 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 7210 "parser_cocci_menhir.ml"
+# 7242 "parser_cocci_menhir.ml"
in
P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
d )
-# 7221 "parser_cocci_menhir.ml"
+# 7253 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7257 "parser_cocci_menhir.ml"
+# 7289 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_comma_list_d_ident_ = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 7269 "parser_cocci_menhir.ml"
+# 7301 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 7276 "parser_cocci_menhir.ml"
+# 7308 "parser_cocci_menhir.ml"
in
P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
d )
-# 7287 "parser_cocci_menhir.ml"
+# 7319 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7323 "parser_cocci_menhir.ml"
+# 7355 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_comma_list_d_ident_ = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 7334 "parser_cocci_menhir.ml"
+# 7366 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 7342 "parser_cocci_menhir.ml"
+# 7374 "parser_cocci_menhir.ml"
in
P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
d )
-# 7353 "parser_cocci_menhir.ml"
+# 7385 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7394 "parser_cocci_menhir.ml"
+# 7426 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_comma_list_d_ident_ = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 7407 "parser_cocci_menhir.ml"
+# 7439 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 7415 "parser_cocci_menhir.ml"
+# 7447 "parser_cocci_menhir.ml"
in
P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)))
d )
-# 7426 "parser_cocci_menhir.ml"
+# 7458 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7467 "parser_cocci_menhir.ml"
+# 7499 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7473 "parser_cocci_menhir.ml"
+# 7505 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 7483 "parser_cocci_menhir.ml"
+# 7515 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 7490 "parser_cocci_menhir.ml"
+# 7522 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
[Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv))] )
-# 7500 "parser_cocci_menhir.ml"
+# 7532 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7546 "parser_cocci_menhir.ml"
+# 7578 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7552 "parser_cocci_menhir.ml"
+# 7584 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 7564 "parser_cocci_menhir.ml"
+# 7596 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 7571 "parser_cocci_menhir.ml"
+# 7603 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
[Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv))] )
-# 7581 "parser_cocci_menhir.ml"
+# 7613 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7627 "parser_cocci_menhir.ml"
+# 7659 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7633 "parser_cocci_menhir.ml"
+# 7665 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 7644 "parser_cocci_menhir.ml"
+# 7676 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 7652 "parser_cocci_menhir.ml"
+# 7684 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
[Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv))] )
-# 7662 "parser_cocci_menhir.ml"
+# 7694 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7713 "parser_cocci_menhir.ml"
+# 7745 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7719 "parser_cocci_menhir.ml"
+# 7751 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 7732 "parser_cocci_menhir.ml"
+# 7764 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 7740 "parser_cocci_menhir.ml"
+# 7772 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
[Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv))] )
-# 7750 "parser_cocci_menhir.ml"
+# 7782 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7811 "parser_cocci_menhir.ml"
+# 7843 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 7816 "parser_cocci_menhir.ml"
+# 7848 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 7822 "parser_cocci_menhir.ml"
+# 7854 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 7827 "parser_cocci_menhir.ml"
+# 7859 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 7833 "parser_cocci_menhir.ml"
+# 7865 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 7838 "parser_cocci_menhir.ml"
+# 7870 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
# 39 "standard.mly"
( None )
-# 7847 "parser_cocci_menhir.ml"
+# 7879 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
[Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] )
-# 7859 "parser_cocci_menhir.ml"
+# 7891 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 7925 "parser_cocci_menhir.ml"
+# 7957 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 7930 "parser_cocci_menhir.ml"
+# 7962 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 7936 "parser_cocci_menhir.ml"
+# 7968 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 7941 "parser_cocci_menhir.ml"
+# 7973 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 7947 "parser_cocci_menhir.ml"
+# 7979 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 7952 "parser_cocci_menhir.ml"
+# 7984 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let x0 : 'tv_storage = Obj.magic x0 in
# 41 "standard.mly"
( Some x )
-# 7963 "parser_cocci_menhir.ml"
+# 7995 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
[Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv))] )
-# 7975 "parser_cocci_menhir.ml"
+# 8007 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _5 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8016 "parser_cocci_menhir.ml"
+# 8048 "parser_cocci_menhir.ml"
) = Obj.magic _5 in
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 8021 "parser_cocci_menhir.ml"
+# 8053 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr_list_option = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 8027 "parser_cocci_menhir.ml"
+# 8059 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_decl_ident = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 925 "parser_cocci_menhir.mly"
( [Ast0.wrap(Ast0.MacroDecl(_1,P.clt2mcode "(" _2,_3,
P.clt2mcode ")" _4,P.clt2mcode ";" _5))] )
-# 8036 "parser_cocci_menhir.ml"
+# 8068 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8107 "parser_cocci_menhir.ml"
+# 8139 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8113 "parser_cocci_menhir.ml"
+# 8145 "parser_cocci_menhir.ml"
) = Obj.magic q in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 8118 "parser_cocci_menhir.ml"
+# 8150 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 8124 "parser_cocci_menhir.ml"
+# 8156 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 8129 "parser_cocci_menhir.ml"
+# 8161 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 8135 "parser_cocci_menhir.ml"
+# 8167 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 8140 "parser_cocci_menhir.ml"
+# 8172 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
# 39 "standard.mly"
( None )
-# 8149 "parser_cocci_menhir.ml"
+# 8181 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
[Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))])
-# 8161 "parser_cocci_menhir.ml"
+# 8193 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8237 "parser_cocci_menhir.ml"
+# 8269 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8243 "parser_cocci_menhir.ml"
+# 8275 "parser_cocci_menhir.ml"
) = Obj.magic q in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 8248 "parser_cocci_menhir.ml"
+# 8280 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 8254 "parser_cocci_menhir.ml"
+# 8286 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 8259 "parser_cocci_menhir.ml"
+# 8291 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 8265 "parser_cocci_menhir.ml"
+# 8297 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 8270 "parser_cocci_menhir.ml"
+# 8302 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let x0 : 'tv_storage = Obj.magic x0 in
# 41 "standard.mly"
( Some x )
-# 8281 "parser_cocci_menhir.ml"
+# 8313 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
[Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv))])
-# 8293 "parser_cocci_menhir.ml"
+# 8325 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8329 "parser_cocci_menhir.ml"
+# 8361 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let id : 'tv_typedef_ident = Obj.magic id in
let t : 'tv_ctype = Obj.magic t in
let s : (
# 53 "parser_cocci_menhir.mly"
(Data.clt)
-# 8336 "parser_cocci_menhir.ml"
+# 8368 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_pv_ in
# 939 "parser_cocci_menhir.mly"
( let s = P.clt2mcode "typedef" s in
[Ast0.wrap(Ast0.Typedef(s,t,id,P.clt2mcode ";" pv))] )
-# 8344 "parser_cocci_menhir.ml"
+# 8376 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
if List.exists circle _1
then Ast0.wrap(Ast0.CIRCLES(_1))
else Ast0.wrap(Ast0.DOTS(_1)) )
-# 8372 "parser_cocci_menhir.ml"
+# 8404 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_define_param_list_option =
# 684 "parser_cocci_menhir.mly"
( _1 )
-# 8396 "parser_cocci_menhir.ml"
+# 8428 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_define_param_list_option =
# 685 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS([])) )
-# 8413 "parser_cocci_menhir.ml"
+# 8445 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_define_param_list_start =
# 667 "parser_cocci_menhir.mly"
( [Ast0.wrap(Ast0.DParam _1)] )
-# 8437 "parser_cocci_menhir.ml"
+# 8469 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8469 "parser_cocci_menhir.ml"
+# 8501 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_ident = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 669 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DParam _1)::
Ast0.wrap(Ast0.DPComma(P.clt2mcode "," _2))::_3 )
-# 8478 "parser_cocci_menhir.ml"
+# 8510 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 8505 "parser_cocci_menhir.ml"
+# 8537 "parser_cocci_menhir.ml"
) = Obj.magic d in
let _startpos = _startpos_d_ in
let _endpos = _endpos_r_ in
# 672 "parser_cocci_menhir.mly"
( (P.mkdpdots "..." d)::
(List.concat (List.map (function x -> x (P.mkdpdots "...")) r)) )
-# 8513 "parser_cocci_menhir.ml"
+# 8545 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 80 "parser_cocci_menhir.mly"
(Data.clt * token)
-# 8534 "parser_cocci_menhir.ml"
+# 8566 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
"unexpected name for a #define")),
Ast0.wrap Ast0.NoParams,
body)) )
-# 8556 "parser_cocci_menhir.ml"
+# 8588 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 8587 "parser_cocci_menhir.ml"
+# 8619 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_define_param_list_option = Obj.magic _2 in
let _1 : (
# 81 "parser_cocci_menhir.mly"
(Data.clt * token * int)
-# 8593 "parser_cocci_menhir.ml"
+# 8625 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
(Semantic_cocci.Semantic
"unexpected name for a #define")),
Ast0.wrap (Ast0.DParams (lp,_2,P.clt2mcode ")" _3)),body)) )
-# 8617 "parser_cocci_menhir.ml"
+# 8649 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_dep =
# 215 "parser_cocci_menhir.mly"
( _1 )
-# 8641 "parser_cocci_menhir.ml"
+# 8673 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_dep =
# 216 "parser_cocci_menhir.mly"
( Ast.AndDep(_1, _3) )
-# 8675 "parser_cocci_menhir.ml"
+# 8707 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_dep =
# 217 "parser_cocci_menhir.mly"
( Ast.OrDep (_1, _3) )
-# 8709 "parser_cocci_menhir.ml"
+# 8741 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_depends =
# 211 "parser_cocci_menhir.mly"
( Ast.NoDep )
-# 8726 "parser_cocci_menhir.ml"
+# 8758 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_depends =
# 212 "parser_cocci_menhir.mly"
( parents )
-# 8758 "parser_cocci_menhir.ml"
+# 8790 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_dexpr =
# 1134 "parser_cocci_menhir.mly"
( _1 )
-# 8782 "parser_cocci_menhir.ml"
+# 8814 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_disable =
# 230 "parser_cocci_menhir.mly"
( List.map P.id2name _2 )
-# 8810 "parser_cocci_menhir.ml"
+# 8842 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 8831 "parser_cocci_menhir.ml"
+# 8863 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_dot_expressions =
# 1143 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Edots(P.clt2mcode "..." _1,None)) )
-# 8838 "parser_cocci_menhir.ml"
+# 8870 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_dot_expressions =
# 1144 "parser_cocci_menhir.mly"
( _1 )
-# 8862 "parser_cocci_menhir.ml"
+# 8894 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 8888 "parser_cocci_menhir.ml"
+# 8920 "parser_cocci_menhir.ml"
) = Obj.magic d in
let c : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8893 "parser_cocci_menhir.ml"
+# 8925 "parser_cocci_menhir.ml"
) = Obj.magic c in
let _startpos = _startpos_c_ in
let _endpos = _endpos_d_ in
# 677 "parser_cocci_menhir.mly"
( function dot_builder ->
[Ast0.wrap(Ast0.DPComma(P.clt2mcode "," c)); dot_builder d] )
-# 8901 "parser_cocci_menhir.ml"
+# 8933 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 8928 "parser_cocci_menhir.ml"
+# 8960 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
( function dot_builder ->
[Ast0.wrap(Ast0.DPComma(P.clt2mcode "," _1));
Ast0.wrap(Ast0.DParam _2)] )
-# 8937 "parser_cocci_menhir.ml"
+# 8969 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 8958 "parser_cocci_menhir.ml"
+# 8990 "parser_cocci_menhir.ml"
) = Obj.magic d in
let _startpos = _startpos_d_ in
let _endpos = _endpos_d_ in
let _v : 'tv_edots_when_TEllipsis_eexpr_ =
-# 1698 "parser_cocci_menhir.mly"
+# 1704 "parser_cocci_menhir.mly"
( (d,None) )
-# 8965 "parser_cocci_menhir.ml"
+# 8997 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 9004 "parser_cocci_menhir.ml"
+# 9036 "parser_cocci_menhir.ml"
) = Obj.magic d in
let _startpos = _startpos_d_ in
let _endpos = _endpos__5_ in
let _v : 'tv_edots_when_TEllipsis_eexpr_ =
-# 1699 "parser_cocci_menhir.mly"
+# 1705 "parser_cocci_menhir.mly"
( (d,Some w) )
-# 9011 "parser_cocci_menhir.ml"
+# 9043 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 9032 "parser_cocci_menhir.ml"
+# 9064 "parser_cocci_menhir.ml"
) = Obj.magic d in
let _startpos = _startpos_d_ in
let _endpos = _endpos_d_ in
let _v : 'tv_edots_when_TEllipsis_initialize_ =
-# 1698 "parser_cocci_menhir.mly"
+# 1704 "parser_cocci_menhir.mly"
( (d,None) )
-# 9039 "parser_cocci_menhir.ml"
+# 9071 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 9078 "parser_cocci_menhir.ml"
+# 9110 "parser_cocci_menhir.ml"
) = Obj.magic d in
let _startpos = _startpos_d_ in
let _endpos = _endpos__5_ in
let _v : 'tv_edots_when_TEllipsis_initialize_ =
-# 1699 "parser_cocci_menhir.mly"
+# 1705 "parser_cocci_menhir.mly"
( (d,Some w) )
-# 9085 "parser_cocci_menhir.ml"
+# 9117 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 9106 "parser_cocci_menhir.ml"
+# 9138 "parser_cocci_menhir.ml"
) = Obj.magic d in
let _startpos = _startpos_d_ in
let _endpos = _endpos_d_ in
let _v : 'tv_edots_when_TEllipsis_struct_decl_ =
-# 1698 "parser_cocci_menhir.mly"
+# 1704 "parser_cocci_menhir.mly"
( (d,None) )
-# 9113 "parser_cocci_menhir.ml"
+# 9145 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let d : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 9152 "parser_cocci_menhir.ml"
+# 9184 "parser_cocci_menhir.ml"
) = Obj.magic d in
let _startpos = _startpos_d_ in
let _endpos = _endpos__5_ in
let _v : 'tv_edots_when_TEllipsis_struct_decl_ =
-# 1699 "parser_cocci_menhir.mly"
+# 1705 "parser_cocci_menhir.mly"
( (d,Some w) )
-# 9159 "parser_cocci_menhir.ml"
+# 9191 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_eexpr =
# 1132 "parser_cocci_menhir.mly"
( _1 )
-# 9183 "parser_cocci_menhir.ml"
+# 9215 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_eexpr_list =
-# 1642 "parser_cocci_menhir.mly"
+# 1648 "parser_cocci_menhir.mly"
(let circle x =
match Ast0.unwrap x with Ast0.Ecircles(_) -> true | _ -> false in
let star x =
if List.exists star _1
then Ast0.wrap(Ast0.STARS(_1))
else Ast0.wrap(Ast0.DOTS(_1)) )
-# 9216 "parser_cocci_menhir.ml"
+# 9248 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_eexpr_list_option =
-# 1681 "parser_cocci_menhir.mly"
+# 1687 "parser_cocci_menhir.mly"
( _1 )
-# 9240 "parser_cocci_menhir.ml"
+# 9272 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_eexpr_list_option =
-# 1682 "parser_cocci_menhir.mly"
+# 1688 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS([])) )
-# 9257 "parser_cocci_menhir.ml"
+# 9289 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_eexpr_list_start =
-# 1669 "parser_cocci_menhir.mly"
+# 1675 "parser_cocci_menhir.mly"
( [_1] )
-# 9281 "parser_cocci_menhir.ml"
+# 9313 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 9313 "parser_cocci_menhir.ml"
+# 9345 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_aexpr = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_eexpr_list_start =
-# 1671 "parser_cocci_menhir.mly"
+# 1677 "parser_cocci_menhir.mly"
( _1::Ast0.wrap(Ast0.EComma(P.clt2mcode "," _2))::_3 )
-# 9321 "parser_cocci_menhir.ml"
+# 9353 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_error_words =
# 1481 "parser_cocci_menhir.mly"
( [Ast0.wrap(Ast0.ERRORWORDS(cl))] )
-# 9365 "parser_cocci_menhir.ml"
+# 9397 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_exists =
# 233 "parser_cocci_menhir.mly"
( Ast.Exists )
-# 9387 "parser_cocci_menhir.ml"
+# 9419 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_exists =
# 234 "parser_cocci_menhir.mly"
( Ast.Forall )
-# 9409 "parser_cocci_menhir.ml"
+# 9441 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_exists =
# 235 "parser_cocci_menhir.mly"
( Ast.ReverseForall )
-# 9435 "parser_cocci_menhir.ml"
+# 9467 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_exists =
# 236 "parser_cocci_menhir.mly"
( Ast.Undetermined )
-# 9452 "parser_cocci_menhir.ml"
+# 9484 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_expr =
# 1130 "parser_cocci_menhir.mly"
( _1 )
-# 9476 "parser_cocci_menhir.ml"
+# 9508 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_expr_dots_TEllipsis_ =
# 1311 "parser_cocci_menhir.mly"
( r )
-# 9500 "parser_cocci_menhir.ml"
+# 9532 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_extends =
# 206 "parser_cocci_menhir.mly"
( () )
-# 9517 "parser_cocci_menhir.ml"
+# 9549 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let parent : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 9542 "parser_cocci_menhir.ml"
+# 9574 "parser_cocci_menhir.ml"
) = Obj.magic parent in
let _startpos = _startpos__1_ in
let _endpos = _endpos_parent_ in
let _v : 'tv_extends =
# 208 "parser_cocci_menhir.mly"
( !Data.install_bindings (parent) )
-# 9549 "parser_cocci_menhir.ml"
+# 9581 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 82 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 9575 "parser_cocci_menhir.ml"
+# 9607 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 82 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 9580 "parser_cocci_menhir.ml"
+# 9612 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
( [Ast0.wrap
(Ast0.FILEINFO(P.id2mcode _1,
P.id2mcode _2))] )
-# 9589 "parser_cocci_menhir.ml"
+# 9621 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_fn_ctype =
# 535 "parser_cocci_menhir.mly"
( P.pointerify ty m )
-# 9619 "parser_cocci_menhir.ml"
+# 9651 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let t : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 9646 "parser_cocci_menhir.ml"
+# 9678 "parser_cocci_menhir.ml"
) = Obj.magic t in
let _startpos = _startpos_t_ in
let _endpos = _endpos_m_ in
( P.pointerify
(Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.VoidType t, None)))
m )
-# 9655 "parser_cocci_menhir.ml"
+# 9687 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_fninfo =
# 723 "parser_cocci_menhir.mly"
( [] )
-# 9672 "parser_cocci_menhir.ml"
+# 9704 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
List.find (function Ast0.FStorage(_) -> true | _ -> false) _2 in
raise (Semantic_cocci.Semantic "duplicate storage")
with Not_found -> (Ast0.FStorage(_1))::_2 )
-# 9706 "parser_cocci_menhir.ml"
+# 9738 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_fninfo =
# 730 "parser_cocci_menhir.mly"
( (Ast0.FType(t))::r )
-# 9736 "parser_cocci_menhir.ml"
+# 9768 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 53 "parser_cocci_menhir.mly"
(Data.clt)
-# 9763 "parser_cocci_menhir.ml"
+# 9795 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) _2 in
raise (Semantic_cocci.Semantic "duplicate inline")
with Not_found -> (Ast0.FInline(P.clt2mcode "inline" _1))::_2 )
-# 9773 "parser_cocci_menhir.ml"
+# 9805 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 55 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 9800 "parser_cocci_menhir.ml"
+# 9832 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) _2 in
raise (Semantic_cocci.Semantic "multiple attributes")
with Not_found -> (Ast0.FAttr(P.id2mcode _1))::_2 )
-# 9810 "parser_cocci_menhir.ml"
+# 9842 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_fninfo_nt =
# 743 "parser_cocci_menhir.mly"
( [] )
-# 9827 "parser_cocci_menhir.ml"
+# 9859 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
List.find (function Ast0.FStorage(_) -> true | _ -> false) _2 in
raise (Semantic_cocci.Semantic "duplicate storage")
with Not_found -> (Ast0.FStorage(_1))::_2 )
-# 9861 "parser_cocci_menhir.ml"
+# 9893 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 53 "parser_cocci_menhir.mly"
(Data.clt)
-# 9888 "parser_cocci_menhir.ml"
+# 9920 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _ = List.find (function Ast0.FInline(_) -> true | _ -> false) _2 in
raise (Semantic_cocci.Semantic "duplicate inline")
with Not_found -> (Ast0.FInline(P.clt2mcode "inline" _1))::_2 )
-# 9898 "parser_cocci_menhir.ml"
+# 9930 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 55 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 9925 "parser_cocci_menhir.ml"
+# 9957 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _ = List.find (function Ast0.FAttr(_) -> true | _ -> false) _2 in
raise (Semantic_cocci.Semantic "duplicate init")
with Not_found -> (Ast0.FAttr(P.id2mcode _1))::_2 )
-# 9935 "parser_cocci_menhir.ml"
+# 9967 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_fun_after_dots =
-# 1590 "parser_cocci_menhir.mly"
+# 1596 "parser_cocci_menhir.mly"
([])
-# 9952 "parser_cocci_menhir.ml"
+# 9984 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_dots =
-# 1591 "parser_cocci_menhir.mly"
+# 1597 "parser_cocci_menhir.mly"
(_2)
-# 9980 "parser_cocci_menhir.ml"
+# 10012 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_dots =
-# 1592 "parser_cocci_menhir.mly"
+# 1598 "parser_cocci_menhir.mly"
(Ast0.wrap(Ast0.Exp(_1))::_2)
-# 10010 "parser_cocci_menhir.ml"
+# 10042 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_dots =
-# 1593 "parser_cocci_menhir.mly"
+# 1599 "parser_cocci_menhir.mly"
(_1@_2)
-# 10040 "parser_cocci_menhir.ml"
+# 10072 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_fun_after_dots_or =
-# 1600 "parser_cocci_menhir.mly"
+# 1606 "parser_cocci_menhir.mly"
([])
-# 10057 "parser_cocci_menhir.ml"
+# 10089 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_dots_or =
-# 1601 "parser_cocci_menhir.mly"
+# 1607 "parser_cocci_menhir.mly"
(_2)
-# 10085 "parser_cocci_menhir.ml"
+# 10117 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_dots_or =
-# 1602 "parser_cocci_menhir.mly"
+# 1608 "parser_cocci_menhir.mly"
(Ast0.wrap(Ast0.Exp(_1))::_2)
-# 10115 "parser_cocci_menhir.ml"
+# 10147 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_dots_or =
-# 1603 "parser_cocci_menhir.mly"
+# 1609 "parser_cocci_menhir.mly"
(_1@_2)
-# 10145 "parser_cocci_menhir.ml"
+# 10177 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_exp =
-# 1596 "parser_cocci_menhir.mly"
+# 1602 "parser_cocci_menhir.mly"
(_1::_2)
-# 10175 "parser_cocci_menhir.ml"
+# 10207 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_fun_after_exp_or =
-# 1606 "parser_cocci_menhir.mly"
+# 1612 "parser_cocci_menhir.mly"
([])
-# 10192 "parser_cocci_menhir.ml"
+# 10224 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_exp_or =
-# 1607 "parser_cocci_menhir.mly"
+# 1613 "parser_cocci_menhir.mly"
(_1::_2)
-# 10222 "parser_cocci_menhir.ml"
+# 10254 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_fun_after_stm =
-# 1585 "parser_cocci_menhir.mly"
+# 1591 "parser_cocci_menhir.mly"
([])
-# 10239 "parser_cocci_menhir.ml"
+# 10271 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_stm =
-# 1586 "parser_cocci_menhir.mly"
+# 1592 "parser_cocci_menhir.mly"
(_1::_2)
-# 10269 "parser_cocci_menhir.ml"
+# 10301 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_fun_after_stm =
-# 1587 "parser_cocci_menhir.mly"
+# 1593 "parser_cocci_menhir.mly"
(_1@_2)
-# 10299 "parser_cocci_menhir.ml"
+# 10331 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_fun_start =
-# 1582 "parser_cocci_menhir.mly"
+# 1588 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS(_1)) )
-# 10323 "parser_cocci_menhir.ml"
+# 10355 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_func_ident =
# 1400 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Id(P.id2mcode _1)) )
-# 10347 "parser_cocci_menhir.ml"
+# 10379 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 61 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 10368 "parser_cocci_menhir.ml"
+# 10400 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1402 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) )
-# 10376 "parser_cocci_menhir.ml"
+# 10408 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 61 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 10397 "parser_cocci_menhir.ml"
+# 10429 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1405 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) )
-# 10405 "parser_cocci_menhir.ml"
+# 10437 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 61 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 10426 "parser_cocci_menhir.ml"
+# 10458 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap
(Ast0.MetaLocalFunc(P.clt2mcode nm clt,constraints,pure)) )
-# 10435 "parser_cocci_menhir.ml"
+# 10467 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rb : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 10495 "parser_cocci_menhir.ml"
+# 10527 "parser_cocci_menhir.ml"
) = Obj.magic rb in
let b : 'tv_fun_start = Obj.magic b in
let lb : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 10501 "parser_cocci_menhir.ml"
+# 10533 "parser_cocci_menhir.ml"
) = Obj.magic lb in
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 10506 "parser_cocci_menhir.ml"
+# 10538 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let d : 'tv_decl_list_decl_ = Obj.magic d in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 10512 "parser_cocci_menhir.ml"
+# 10544 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let i : 'tv_func_ident = Obj.magic i in
let f : 'tv_fninfo = Obj.magic f in
P.clt2mcode ")" rp,
P.clt2mcode "{" lb, b,
P.clt2mcode "}" rb)) )
-# 10526 "parser_cocci_menhir.ml"
+# 10558 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pt : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 10572 "parser_cocci_menhir.ml"
+# 10604 "parser_cocci_menhir.ml"
) = Obj.magic pt in
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 10577 "parser_cocci_menhir.ml"
+# 10609 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let d : 'tv_decl_list_name_opt_decl_ = Obj.magic d in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 10583 "parser_cocci_menhir.ml"
+# 10615 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let id : 'tv_func_ident = Obj.magic id in
let t : 'tv_ctype = Obj.magic t in
# 39 "standard.mly"
( None )
-# 10593 "parser_cocci_menhir.ml"
+# 10625 "parser_cocci_menhir.ml"
in
(Ast0.FunctionType(Some t,
P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
id, P.clt2mcode ";" pt)) )
-# 10605 "parser_cocci_menhir.ml"
+# 10637 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pt : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 10656 "parser_cocci_menhir.ml"
+# 10688 "parser_cocci_menhir.ml"
) = Obj.magic pt in
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 10661 "parser_cocci_menhir.ml"
+# 10693 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let d : 'tv_decl_list_name_opt_decl_ = Obj.magic d in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 10667 "parser_cocci_menhir.ml"
+# 10699 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let id : 'tv_func_ident = Obj.magic id in
let t : 'tv_ctype = Obj.magic t in
# 41 "standard.mly"
( Some x )
-# 10679 "parser_cocci_menhir.ml"
+# 10711 "parser_cocci_menhir.ml"
in
(Ast0.FunctionType(Some t,
P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
id, P.clt2mcode ";" pt)) )
-# 10691 "parser_cocci_menhir.ml"
+# 10723 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pt : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 10737 "parser_cocci_menhir.ml"
+# 10769 "parser_cocci_menhir.ml"
) = Obj.magic pt in
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 10742 "parser_cocci_menhir.ml"
+# 10774 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let d : 'tv_decl_list_name_opt_decl_ = Obj.magic d in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 10748 "parser_cocci_menhir.ml"
+# 10780 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let id : 'tv_func_ident = Obj.magic id in
let t : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 10754 "parser_cocci_menhir.ml"
+# 10786 "parser_cocci_menhir.ml"
) = Obj.magic t in
let _startpos = _startpos_t_ in
let _endpos = _endpos_pt_ in
# 39 "standard.mly"
( None )
-# 10762 "parser_cocci_menhir.ml"
+# 10794 "parser_cocci_menhir.ml"
in
(Ast0.FunctionType(Some t,
P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
id, P.clt2mcode ";" pt)) )
-# 10775 "parser_cocci_menhir.ml"
+# 10807 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pt : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 10826 "parser_cocci_menhir.ml"
+# 10858 "parser_cocci_menhir.ml"
) = Obj.magic pt in
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 10831 "parser_cocci_menhir.ml"
+# 10863 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let d : 'tv_decl_list_name_opt_decl_ = Obj.magic d in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 10837 "parser_cocci_menhir.ml"
+# 10869 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let id : 'tv_func_ident = Obj.magic id in
let t : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 10843 "parser_cocci_menhir.ml"
+# 10875 "parser_cocci_menhir.ml"
) = Obj.magic t in
let x0 : 'tv_storage = Obj.magic x0 in
let _startpos = _startpos_x0_ in
# 41 "standard.mly"
( Some x )
-# 10853 "parser_cocci_menhir.ml"
+# 10885 "parser_cocci_menhir.ml"
in
(Ast0.FunctionType(Some t,
P.clt2mcode "(" lp, d, P.clt2mcode ")" rp)),
id, P.clt2mcode ";" pt)) )
-# 10866 "parser_cocci_menhir.ml"
+# 10898 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_generic_ctype =
# 442 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.ImplicitInt(q)) )
-# 10890 "parser_cocci_menhir.ml"
+# 10922 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 10911 "parser_cocci_menhir.ml"
+# 10943 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let _startpos = _startpos_ty_ in
let _endpos = _endpos_ty_ in
# 39 "standard.mly"
( None )
-# 10919 "parser_cocci_menhir.ml"
+# 10951 "parser_cocci_menhir.ml"
in
# 444 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.CharType ty, q)) )
-# 10925 "parser_cocci_menhir.ml"
+# 10957 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 10951 "parser_cocci_menhir.ml"
+# 10983 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let x0 : 'tv_ctype_qualif = Obj.magic x0 in
let _startpos = _startpos_x0_ in
# 41 "standard.mly"
( Some x )
-# 10961 "parser_cocci_menhir.ml"
+# 10993 "parser_cocci_menhir.ml"
in
# 444 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.CharType ty, q)) )
-# 10967 "parser_cocci_menhir.ml"
+# 10999 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 10988 "parser_cocci_menhir.ml"
+# 11020 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let _startpos = _startpos_ty_ in
let _endpos = _endpos_ty_ in
# 39 "standard.mly"
( None )
-# 10996 "parser_cocci_menhir.ml"
+# 11028 "parser_cocci_menhir.ml"
in
# 446 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.ShortType ty, q)) )
-# 11002 "parser_cocci_menhir.ml"
+# 11034 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 11028 "parser_cocci_menhir.ml"
+# 11060 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let x0 : 'tv_ctype_qualif = Obj.magic x0 in
let _startpos = _startpos_x0_ in
# 41 "standard.mly"
( Some x )
-# 11038 "parser_cocci_menhir.ml"
+# 11070 "parser_cocci_menhir.ml"
in
# 446 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.ShortType ty, q)) )
-# 11044 "parser_cocci_menhir.ml"
+# 11076 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 11065 "parser_cocci_menhir.ml"
+# 11097 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let _startpos = _startpos_ty_ in
let _endpos = _endpos_ty_ in
# 39 "standard.mly"
( None )
-# 11073 "parser_cocci_menhir.ml"
+# 11105 "parser_cocci_menhir.ml"
in
# 448 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.IntType ty, q)) )
-# 11079 "parser_cocci_menhir.ml"
+# 11111 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 11105 "parser_cocci_menhir.ml"
+# 11137 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let x0 : 'tv_ctype_qualif = Obj.magic x0 in
let _startpos = _startpos_x0_ in
# 41 "standard.mly"
( Some x )
-# 11115 "parser_cocci_menhir.ml"
+# 11147 "parser_cocci_menhir.ml"
in
# 448 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.IntType ty, q)) )
-# 11121 "parser_cocci_menhir.ml"
+# 11153 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let t : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 11142 "parser_cocci_menhir.ml"
+# 11174 "parser_cocci_menhir.ml"
) = Obj.magic t in
let _startpos = _startpos_t_ in
let _endpos = _endpos_t_ in
let _v : 'tv_generic_ctype =
# 450 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.DoubleType t, None)) )
-# 11149 "parser_cocci_menhir.ml"
+# 11181 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let t : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 11170 "parser_cocci_menhir.ml"
+# 11202 "parser_cocci_menhir.ml"
) = Obj.magic t in
let _startpos = _startpos_t_ in
let _endpos = _endpos_t_ in
let _v : 'tv_generic_ctype =
# 452 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.FloatType t, None)) )
-# 11177 "parser_cocci_menhir.ml"
+# 11209 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 11198 "parser_cocci_menhir.ml"
+# 11230 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let _startpos = _startpos_ty_ in
let _endpos = _endpos_ty_ in
# 39 "standard.mly"
( None )
-# 11206 "parser_cocci_menhir.ml"
+# 11238 "parser_cocci_menhir.ml"
in
# 454 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.LongType ty, q)) )
-# 11212 "parser_cocci_menhir.ml"
+# 11244 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty : (
# 49 "parser_cocci_menhir.mly"
(Data.clt)
-# 11238 "parser_cocci_menhir.ml"
+# 11270 "parser_cocci_menhir.ml"
) = Obj.magic ty in
let x0 : 'tv_ctype_qualif = Obj.magic x0 in
let _startpos = _startpos_x0_ in
# 41 "standard.mly"
( Some x )
-# 11248 "parser_cocci_menhir.ml"
+# 11280 "parser_cocci_menhir.ml"
in
# 454 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.BaseType(P.clt2mcode Ast.LongType ty, q)) )
-# 11254 "parser_cocci_menhir.ml"
+# 11286 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_generic_ctype =
# 456 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.StructUnionName(s, Some i)) )
-# 11284 "parser_cocci_menhir.ml"
+# 11316 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let r : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 11320 "parser_cocci_menhir.ml"
+# 11352 "parser_cocci_menhir.ml"
) = Obj.magic r in
let d : 'tv_struct_decl_list = Obj.magic d in
let l : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 11326 "parser_cocci_menhir.ml"
+# 11358 "parser_cocci_menhir.ml"
) = Obj.magic l in
let s : 'tv_struct_or_union = Obj.magic s in
let _startpos = _startpos_s_ in
# 39 "standard.mly"
( None )
-# 11335 "parser_cocci_menhir.ml"
+# 11367 "parser_cocci_menhir.ml"
in
Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
P.clt2mcode "{" l,
d, P.clt2mcode "}" r)) )
-# 11345 "parser_cocci_menhir.ml"
+# 11377 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let r : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 11386 "parser_cocci_menhir.ml"
+# 11418 "parser_cocci_menhir.ml"
) = Obj.magic r in
let d : 'tv_struct_decl_list = Obj.magic d in
let l : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 11392 "parser_cocci_menhir.ml"
+# 11424 "parser_cocci_menhir.ml"
) = Obj.magic l in
let x0 : 'tv_ident = Obj.magic x0 in
let s : 'tv_struct_or_union = Obj.magic s in
# 41 "standard.mly"
( Some x )
-# 11403 "parser_cocci_menhir.ml"
+# 11435 "parser_cocci_menhir.ml"
in
Ast0.wrap(Ast0.StructUnionDef(Ast0.wrap(Ast0.StructUnionName(s, i)),
P.clt2mcode "{" l,
d, P.clt2mcode "}" r)) )
-# 11413 "parser_cocci_menhir.ml"
+# 11445 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let r : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 11449 "parser_cocci_menhir.ml"
+# 11481 "parser_cocci_menhir.ml"
) = Obj.magic r in
let d : 'tv_struct_decl_list = Obj.magic d in
let l : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 11455 "parser_cocci_menhir.ml"
+# 11487 "parser_cocci_menhir.ml"
) = Obj.magic l in
let s : (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 11460 "parser_cocci_menhir.ml"
+# 11492 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_r_ in
Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) in
Ast0.wrap
(Ast0.StructUnionDef(ty,P.clt2mcode "{" l,d,P.clt2mcode "}" r)) )
-# 11471 "parser_cocci_menhir.ml"
+# 11503 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let p : (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 11501 "parser_cocci_menhir.ml"
+# 11533 "parser_cocci_menhir.ml"
) = Obj.magic p in
let r : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 11506 "parser_cocci_menhir.ml"
+# 11538 "parser_cocci_menhir.ml"
) = Obj.magic r in
let _startpos = _startpos_r_ in
let _endpos = _endpos_p_ in
let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
Ast0.Impure (*will be ignored*))) )
-# 11518 "parser_cocci_menhir.ml"
+# 11550 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let p : (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 11539 "parser_cocci_menhir.ml"
+# 11571 "parser_cocci_menhir.ml"
) = Obj.magic p in
let _startpos = _startpos_p_ in
let _endpos = _endpos_p_ in
let _v : 'tv_generic_ctype =
# 478 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.TypeName(P.id2mcode p)) )
-# 11546 "parser_cocci_menhir.ml"
+# 11578 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let p : (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 11567 "parser_cocci_menhir.ml"
+# 11599 "parser_cocci_menhir.ml"
) = Obj.magic p in
let _startpos = _startpos_p_ in
let _endpos = _endpos_p_ in
# 480 "parser_cocci_menhir.mly"
( let (nm,pure,clt) = p in
Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) )
-# 11575 "parser_cocci_menhir.ml"
+# 11607 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_ident =
# 1413 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Id(P.id2mcode _1)) )
-# 11599 "parser_cocci_menhir.ml"
+# 11631 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 61 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 11620 "parser_cocci_menhir.ml"
+# 11652 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1415 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) )
-# 11628 "parser_cocci_menhir.ml"
+# 11660 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_ident_or_const =
# 1371 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))) )
-# 11652 "parser_cocci_menhir.ml"
+# 11684 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 11673 "parser_cocci_menhir.ml"
+# 11705 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1373 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) )
-# 11681 "parser_cocci_menhir.ml"
+# 11713 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 11706 "parser_cocci_menhir.ml"
+# 11738 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_incl =
# 247 "parser_cocci_menhir.mly"
( Common.Left(P.id2name _2) )
-# 11713 "parser_cocci_menhir.ml"
+# 11745 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 78 "parser_cocci_menhir.mly"
(string)
-# 11738 "parser_cocci_menhir.ml"
+# 11770 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_incl =
# 248 "parser_cocci_menhir.mly"
( Common.Right _2 )
-# 11745 "parser_cocci_menhir.ml"
+# 11777 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 145 "parser_cocci_menhir.mly"
((string,string) Common.either list)
-# 11773 "parser_cocci_menhir.ml"
+# 11805 "parser_cocci_menhir.ml"
) =
# 243 "parser_cocci_menhir.mly"
( _1 )
-# 11777 "parser_cocci_menhir.ml"
+# 11809 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 145 "parser_cocci_menhir.mly"
((string,string) Common.either list)
-# 11805 "parser_cocci_menhir.ml"
+# 11837 "parser_cocci_menhir.ml"
) =
# 244 "parser_cocci_menhir.mly"
( _1 )
-# 11809 "parser_cocci_menhir.ml"
+# 11841 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 79 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 11830 "parser_cocci_menhir.ml"
+# 11862 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
P.clt2mcode
(Ast.Local (Parse_aux.str2inc (P.id2name _1)))
(P.drop_bef clt))) )
-# 11845 "parser_cocci_menhir.ml"
+# 11877 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 79 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 11866 "parser_cocci_menhir.ml"
+# 11898 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
P.clt2mcode
(Ast.NonLocal (Parse_aux.str2inc (P.id2name _1)))
(P.drop_bef clt))) )
-# 11881 "parser_cocci_menhir.ml"
+# 11913 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 606 "parser_cocci_menhir.mly"
( let ty = Ast0.wrap(Ast0.TopExp(Ast0.wrap(Ast0.TypeExp(t)))) in
d (Ast0.wrap(Ast0.DOTS([ty]))) )
-# 11916 "parser_cocci_menhir.ml"
+# 11948 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
| _ -> b)
| _ -> b in
_1 (Ast0.wrap(Ast0.DOTS(body))) )
-# 11958 "parser_cocci_menhir.ml"
+# 11990 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_initialize =
# 1008 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitExpr(_1)) )
-# 11982 "parser_cocci_menhir.ml"
+# 12014 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12013 "parser_cocci_menhir.ml"
+# 12045 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_initialize_list = Obj.magic _2 in
let _1 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12019 "parser_cocci_menhir.ml"
+# 12051 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_initialize =
# 1010 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitList(P.clt2mcode "{" _1,_2,P.clt2mcode "}" _3)) )
-# 12026 "parser_cocci_menhir.ml"
+# 12058 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12052 "parser_cocci_menhir.ml"
+# 12084 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12057 "parser_cocci_menhir.ml"
+# 12089 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
( Ast0.wrap
(Ast0.InitList(P.clt2mcode "{" _1,Ast0.wrap(Ast0.DOTS []),
P.clt2mcode "}" _2)) )
-# 12066 "parser_cocci_menhir.ml"
+# 12098 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_initialize2 =
# 1019 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitExpr(_1)) )
-# 12090 "parser_cocci_menhir.ml"
+# 12122 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12121 "parser_cocci_menhir.ml"
+# 12153 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_initialize_list = Obj.magic _2 in
let _1 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12127 "parser_cocci_menhir.ml"
+# 12159 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_initialize2 =
# 1021 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitList(P.clt2mcode "{" _1,_2,P.clt2mcode "}" _3)) )
-# 12134 "parser_cocci_menhir.ml"
+# 12166 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12160 "parser_cocci_menhir.ml"
+# 12192 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 12165 "parser_cocci_menhir.ml"
+# 12197 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
( Ast0.wrap
(Ast0.InitList(P.clt2mcode "{" _1,Ast0.wrap(Ast0.DOTS []),
P.clt2mcode "}" _2)) )
-# 12174 "parser_cocci_menhir.ml"
+# 12206 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 12211 "parser_cocci_menhir.ml"
+# 12243 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_ident = Obj.magic _2 in
let _1 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 12217 "parser_cocci_menhir.ml"
+# 12249 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__4_ in
let _v : 'tv_initialize2 =
# 1028 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitGccDotName(P.clt2mcode "." _1,_2,P.clt2mcode "=" _3,_4)) )
-# 12224 "parser_cocci_menhir.ml"
+# 12256 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 12256 "parser_cocci_menhir.ml"
+# 12288 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_ident = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_initialize2 =
# 1030 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitGccName(_1,P.clt2mcode ":" _2,_3)) )
-# 12264 "parser_cocci_menhir.ml"
+# 12296 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 12306 "parser_cocci_menhir.ml"
+# 12338 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 12311 "parser_cocci_menhir.ml"
+# 12343 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 12317 "parser_cocci_menhir.ml"
+# 12349 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__5_ in
# 1032 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitGccIndex(P.clt2mcode "[" _1,_2,P.clt2mcode "]" _3,
P.clt2mcode "=" _4,_5)) )
-# 12325 "parser_cocci_menhir.ml"
+# 12357 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _6 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 12377 "parser_cocci_menhir.ml"
+# 12409 "parser_cocci_menhir.ml"
) = Obj.magic _6 in
let _5 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 12382 "parser_cocci_menhir.ml"
+# 12414 "parser_cocci_menhir.ml"
) = Obj.magic _5 in
let _4 : 'tv_eexpr = Obj.magic _4 in
let _3 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 12388 "parser_cocci_menhir.ml"
+# 12420 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 12394 "parser_cocci_menhir.ml"
+# 12426 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__7_ in
# 1035 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.InitGccRange(P.clt2mcode "[" _1,_2,P.clt2mcode "..." _3,
_4,P.clt2mcode "]" _5,P.clt2mcode "=" _6,_7)) )
-# 12402 "parser_cocci_menhir.ml"
+# 12434 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_initialize_list =
# 1039 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS(_1)) )
-# 12426 "parser_cocci_menhir.ml"
+# 12458 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 12452 "parser_cocci_menhir.ml"
+# 12484 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_initialize2 = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_initialize_list_start =
# 1042 "parser_cocci_menhir.mly"
( [_1;Ast0.wrap(Ast0.IComma(P.clt2mcode "," _2))] )
-# 12460 "parser_cocci_menhir.ml"
+# 12492 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 12492 "parser_cocci_menhir.ml"
+# 12524 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_initialize2 = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_initialize_list_start =
# 1044 "parser_cocci_menhir.mly"
( _1::Ast0.wrap(Ast0.IComma(P.clt2mcode "," _2))::_3 )
-# 12500 "parser_cocci_menhir.ml"
+# 12532 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 1047 "parser_cocci_menhir.mly"
( (P.mkidots "..." d)::
(List.concat(List.map (function x -> x (P.mkidots "...")) r)) )
-# 12531 "parser_cocci_menhir.ml"
+# 12563 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_invalid =
# 1140 "parser_cocci_menhir.mly"
( raise (Semantic_cocci.Semantic "not matchable") )
-# 12553 "parser_cocci_menhir.ml"
+# 12585 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_is_expression =
# 239 "parser_cocci_menhir.mly"
( false )
-# 12570 "parser_cocci_menhir.ml"
+# 12602 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_is_expression =
# 240 "parser_cocci_menhir.mly"
( true )
-# 12592 "parser_cocci_menhir.ml"
+# 12624 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_ctype_ =
-# 1752 "parser_cocci_menhir.mly"
+# 1756 "parser_cocci_menhir.mly"
( Common.Left t )
-# 12620 "parser_cocci_menhir.ml"
+# 12652 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_ctype_ =
-# 1753 "parser_cocci_menhir.mly"
+# 1757 "parser_cocci_menhir.mly"
( Common.Right t )
-# 12648 "parser_cocci_menhir.ml"
+# 12680 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_decl_var_ =
-# 1752 "parser_cocci_menhir.mly"
+# 1756 "parser_cocci_menhir.mly"
( Common.Left t )
-# 12676 "parser_cocci_menhir.ml"
+# 12708 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_decl_var_ =
-# 1753 "parser_cocci_menhir.mly"
+# 1757 "parser_cocci_menhir.mly"
( Common.Right t )
-# 12704 "parser_cocci_menhir.ml"
+# 12736 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_dexpr_ =
-# 1752 "parser_cocci_menhir.mly"
+# 1756 "parser_cocci_menhir.mly"
( Common.Left t )
-# 12732 "parser_cocci_menhir.ml"
+# 12764 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_dexpr_ =
-# 1753 "parser_cocci_menhir.mly"
+# 1757 "parser_cocci_menhir.mly"
( Common.Right t )
-# 12760 "parser_cocci_menhir.ml"
+# 12792 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_nest_start_ =
-# 1752 "parser_cocci_menhir.mly"
+# 1756 "parser_cocci_menhir.mly"
( Common.Left t )
-# 12788 "parser_cocci_menhir.ml"
+# 12820 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_nest_start_ =
-# 1753 "parser_cocci_menhir.mly"
+# 1757 "parser_cocci_menhir.mly"
( Common.Right t )
-# 12816 "parser_cocci_menhir.ml"
+# 12848 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_single_statement_ =
-# 1752 "parser_cocci_menhir.mly"
+# 1756 "parser_cocci_menhir.mly"
( Common.Left t )
-# 12844 "parser_cocci_menhir.ml"
+# 12876 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos_t_ in
let _v : 'tv_iso_single_statement_ =
-# 1753 "parser_cocci_menhir.mly"
+# 1757 "parser_cocci_menhir.mly"
( Common.Right t )
-# 12872 "parser_cocci_menhir.ml"
+# 12904 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 12910 "parser_cocci_menhir.ml"
+# 12942 "parser_cocci_menhir.ml"
) =
-# 1724 "parser_cocci_menhir.mly"
+# 1728 "parser_cocci_menhir.mly"
( P.iso_adjust (function x -> Ast0.ExprTag x) e1 el )
-# 12914 "parser_cocci_menhir.ml"
+# 12946 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 12952 "parser_cocci_menhir.ml"
+# 12984 "parser_cocci_menhir.ml"
) =
-# 1726 "parser_cocci_menhir.mly"
+# 1730 "parser_cocci_menhir.mly"
( P.iso_adjust (function x -> Ast0.ArgExprTag x) e1 el )
-# 12956 "parser_cocci_menhir.ml"
+# 12988 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 12994 "parser_cocci_menhir.ml"
+# 13026 "parser_cocci_menhir.ml"
) =
-# 1728 "parser_cocci_menhir.mly"
+# 1732 "parser_cocci_menhir.mly"
( P.iso_adjust (function x -> Ast0.TestExprTag x) e1 el )
-# 12998 "parser_cocci_menhir.ml"
+# 13030 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 13036 "parser_cocci_menhir.ml"
+# 13068 "parser_cocci_menhir.ml"
) =
-# 1730 "parser_cocci_menhir.mly"
+# 1734 "parser_cocci_menhir.mly"
( P.iso_adjust (function x -> Ast0.StmtTag x) s1 sl )
-# 13040 "parser_cocci_menhir.ml"
+# 13072 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 13078 "parser_cocci_menhir.ml"
+# 13110 "parser_cocci_menhir.ml"
) =
-# 1732 "parser_cocci_menhir.mly"
+# 1736 "parser_cocci_menhir.mly"
( P.iso_adjust (function x -> Ast0.TypeCTag x) t1 tl )
-# 13082 "parser_cocci_menhir.ml"
+# 13114 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 13120 "parser_cocci_menhir.ml"
+# 13152 "parser_cocci_menhir.ml"
) =
-# 1734 "parser_cocci_menhir.mly"
+# 1738 "parser_cocci_menhir.mly"
( P.iso_adjust (function x -> Ast0.DotsStmtTag x) e1 el )
-# 13124 "parser_cocci_menhir.ml"
+# 13156 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 13162 "parser_cocci_menhir.ml"
+# 13194 "parser_cocci_menhir.ml"
) =
-# 1736 "parser_cocci_menhir.mly"
+# 1740 "parser_cocci_menhir.mly"
( let check_one = function
[x] -> x
| _ ->
| Common.Right x -> Common.Right(check_one x))
dl in
P.iso_adjust (function x -> Ast0.DeclTag x) d1 dl )
-# 13179 "parser_cocci_menhir.ml"
+# 13211 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 164 "parser_cocci_menhir.mly"
((Ast_cocci.metavar,Ast_cocci.metavar) Common.either list)
-# 13203 "parser_cocci_menhir.ml"
+# 13235 "parser_cocci_menhir.ml"
) =
# 181 "parser_cocci_menhir.mly"
( m "" )
-# 13207 "parser_cocci_menhir.ml"
+# 13239 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 148 "parser_cocci_menhir.mly"
(Ast_cocci.rulename)
-# 13235 "parser_cocci_menhir.ml"
+# 13267 "parser_cocci_menhir.ml"
) =
# 196 "parser_cocci_menhir.mly"
( P.make_iso_rule_name_result (P.id2name nm) )
-# 13239 "parser_cocci_menhir.ml"
+# 13271 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 13260 "parser_cocci_menhir.ml"
+# 13292 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_iter_ident =
# 1427 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Id(P.id2mcode _1)) )
-# 13267 "parser_cocci_menhir.ml"
+# 13299 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 62 "parser_cocci_menhir.mly"
(Parse_aux.idinfo)
-# 13288 "parser_cocci_menhir.ml"
+# 13320 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1429 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) )
-# 13296 "parser_cocci_menhir.ml"
+# 13328 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_TMul_ =
# 114 "standard.mly"
( [] )
-# 13313 "parser_cocci_menhir.ml"
+# 13345 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let x : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 13340 "parser_cocci_menhir.ml"
+# 13372 "parser_cocci_menhir.ml"
) = Obj.magic x in
let _startpos = _startpos_x_ in
let _endpos = _endpos_xs_ in
let _v : 'tv_list_TMul_ =
# 116 "standard.mly"
( x :: xs )
-# 13347 "parser_cocci_menhir.ml"
+# 13379 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_array_dec_ =
# 114 "standard.mly"
( [] )
-# 13364 "parser_cocci_menhir.ml"
+# 13396 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_array_dec_ =
# 116 "standard.mly"
( x :: xs )
-# 13394 "parser_cocci_menhir.ml"
+# 13426 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_case_line_ =
# 114 "standard.mly"
( [] )
-# 13411 "parser_cocci_menhir.ml"
+# 13443 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_case_line_ =
# 116 "standard.mly"
( x :: xs )
-# 13441 "parser_cocci_menhir.ml"
+# 13473 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_comma_decls_TEllipsis_decl__ =
# 114 "standard.mly"
( [] )
-# 13458 "parser_cocci_menhir.ml"
+# 13490 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_comma_decls_TEllipsis_decl__ =
# 116 "standard.mly"
( x :: xs )
-# 13488 "parser_cocci_menhir.ml"
+# 13520 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_comma_decls_TEllipsis_name_opt_decl__ =
# 114 "standard.mly"
( [] )
-# 13505 "parser_cocci_menhir.ml"
+# 13537 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_comma_decls_TEllipsis_name_opt_decl__ =
# 116 "standard.mly"
( x :: xs )
-# 13535 "parser_cocci_menhir.ml"
+# 13567 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_dp_comma_args_TEllipsis__ =
# 114 "standard.mly"
( [] )
-# 13552 "parser_cocci_menhir.ml"
+# 13584 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_dp_comma_args_TEllipsis__ =
# 116 "standard.mly"
( x :: xs )
-# 13582 "parser_cocci_menhir.ml"
+# 13614 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_incl_ =
# 114 "standard.mly"
( [] )
-# 13599 "parser_cocci_menhir.ml"
+# 13631 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_incl_ =
# 116 "standard.mly"
( x :: xs )
-# 13629 "parser_cocci_menhir.ml"
+# 13661 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_ctype__ =
# 114 "standard.mly"
( [] )
-# 13646 "parser_cocci_menhir.ml"
+# 13678 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_ctype__ =
# 116 "standard.mly"
( x :: xs )
-# 13676 "parser_cocci_menhir.ml"
+# 13708 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_decl_var__ =
# 114 "standard.mly"
( [] )
-# 13693 "parser_cocci_menhir.ml"
+# 13725 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_decl_var__ =
# 116 "standard.mly"
( x :: xs )
-# 13723 "parser_cocci_menhir.ml"
+# 13755 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_dexpr__ =
# 114 "standard.mly"
( [] )
-# 13740 "parser_cocci_menhir.ml"
+# 13772 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_dexpr__ =
# 116 "standard.mly"
( x :: xs )
-# 13770 "parser_cocci_menhir.ml"
+# 13802 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_nest_start__ =
# 114 "standard.mly"
( [] )
-# 13787 "parser_cocci_menhir.ml"
+# 13819 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_nest_start__ =
# 116 "standard.mly"
( x :: xs )
-# 13817 "parser_cocci_menhir.ml"
+# 13849 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_single_statement__ =
# 114 "standard.mly"
( [] )
-# 13834 "parser_cocci_menhir.ml"
+# 13866 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_iso_single_statement__ =
# 116 "standard.mly"
( x :: xs )
-# 13864 "parser_cocci_menhir.ml"
+# 13896 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_ctype__ =
# 114 "standard.mly"
( [] )
-# 13881 "parser_cocci_menhir.ml"
+# 13913 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_ctype__ =
# 116 "standard.mly"
( x :: xs )
-# 13911 "parser_cocci_menhir.ml"
+# 13943 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_eexpr__ =
# 114 "standard.mly"
( [] )
-# 13928 "parser_cocci_menhir.ml"
+# 13960 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_eexpr__ =
# 116 "standard.mly"
( x :: xs )
-# 13958 "parser_cocci_menhir.ml"
+# 13990 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_fun_after_dots_or__ =
# 114 "standard.mly"
( [] )
-# 13975 "parser_cocci_menhir.ml"
+# 14007 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_fun_after_dots_or__ =
# 116 "standard.mly"
( x :: xs )
-# 14005 "parser_cocci_menhir.ml"
+# 14037 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_fun_start__ =
# 114 "standard.mly"
( [] )
-# 14022 "parser_cocci_menhir.ml"
+# 14054 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_fun_start__ =
# 116 "standard.mly"
( x :: xs )
-# 14052 "parser_cocci_menhir.ml"
+# 14084 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_rule_elem_statement__ =
# 114 "standard.mly"
( [] )
-# 14069 "parser_cocci_menhir.ml"
+# 14101 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_rule_elem_statement__ =
# 116 "standard.mly"
( x :: xs )
-# 14099 "parser_cocci_menhir.ml"
+# 14131 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_statement__ =
# 114 "standard.mly"
( [] )
-# 14116 "parser_cocci_menhir.ml"
+# 14148 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_mzl_statement__ =
# 116 "standard.mly"
( x :: xs )
-# 14146 "parser_cocci_menhir.ml"
+# 14178 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_pair_edots_when_TEllipsis_eexpr__dexpr__ =
# 114 "standard.mly"
( [] )
-# 14163 "parser_cocci_menhir.ml"
+# 14195 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 70 "standard.mly"
( (x, y) )
-# 14202 "parser_cocci_menhir.ml"
+# 14234 "parser_cocci_menhir.ml"
in
# 116 "standard.mly"
( x :: xs )
-# 14208 "parser_cocci_menhir.ml"
+# 14240 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_whenppdecs_ =
# 114 "standard.mly"
( [] )
-# 14225 "parser_cocci_menhir.ml"
+# 14257 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_list_whenppdecs_ =
# 116 "standard.mly"
( x :: xs )
-# 14255 "parser_cocci_menhir.ml"
+# 14287 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_choose_iso_ =
# 57 "standard.mly"
( [] )
-# 14272 "parser_cocci_menhir.ml"
+# 14304 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_choose_iso_ =
# 59 "standard.mly"
( x )
-# 14296 "parser_cocci_menhir.ml"
+# 14328 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_disable_ =
# 57 "standard.mly"
( [] )
-# 14313 "parser_cocci_menhir.ml"
+# 14345 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_disable_ =
# 59 "standard.mly"
( x )
-# 14337 "parser_cocci_menhir.ml"
+# 14369 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_error_words_ =
# 57 "standard.mly"
( [] )
-# 14354 "parser_cocci_menhir.ml"
+# 14386 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_error_words_ =
# 59 "standard.mly"
( x )
-# 14378 "parser_cocci_menhir.ml"
+# 14410 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_filespec_ =
# 57 "standard.mly"
( [] )
-# 14395 "parser_cocci_menhir.ml"
+# 14427 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_filespec_ =
# 59 "standard.mly"
( x )
-# 14419 "parser_cocci_menhir.ml"
+# 14451 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_minus_start_ =
# 57 "standard.mly"
( [] )
-# 14436 "parser_cocci_menhir.ml"
+# 14468 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_minus_start_ =
# 59 "standard.mly"
( x )
-# 14460 "parser_cocci_menhir.ml"
+# 14492 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_ceq_ =
# 57 "standard.mly"
( [] )
-# 14477 "parser_cocci_menhir.ml"
+# 14509 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_ceq_ =
# 59 "standard.mly"
( x )
-# 14501 "parser_cocci_menhir.ml"
+# 14533 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_eq_ =
# 57 "standard.mly"
( [] )
-# 14518 "parser_cocci_menhir.ml"
+# 14550 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_eq_ =
# 59 "standard.mly"
( x )
-# 14542 "parser_cocci_menhir.ml"
+# 14574 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_eqe_ =
# 57 "standard.mly"
( [] )
-# 14559 "parser_cocci_menhir.ml"
+# 14591 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_eqe_ =
# 59 "standard.mly"
( x )
-# 14583 "parser_cocci_menhir.ml"
+# 14615 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_pos_ =
# 57 "standard.mly"
( [] )
-# 14600 "parser_cocci_menhir.ml"
+# 14632 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_not_pos_ =
# 59 "standard.mly"
( x )
-# 14624 "parser_cocci_menhir.ml"
+# 14656 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_plus_start_ =
# 57 "standard.mly"
( [] )
-# 14641 "parser_cocci_menhir.ml"
+# 14673 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_loption_plus_start_ =
# 59 "standard.mly"
( x )
-# 14665 "parser_cocci_menhir.ml"
+# 14697 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_meta_exp_type =
# 429 "parser_cocci_menhir.mly"
( [Ast0_cocci.ast0_type_to_type t] )
-# 14689 "parser_cocci_menhir.ml"
+# 14721 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( List.map
(function x -> P.ty_pointerify (Ast0_cocci.ast0_type_to_type x) m)
t )
-# 14729 "parser_cocci_menhir.ml"
+# 14761 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 14760 "parser_cocci_menhir.ml"
+# 14792 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_meta_ident =
# 1325 "parser_cocci_menhir.mly"
( (Some _1,P.id2name _3) )
-# 14767 "parser_cocci_menhir.ml"
+# 14799 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 156 "parser_cocci_menhir.mly"
((Ast_cocci.metavar,Ast_cocci.metavar) Common.either list)
-# 14791 "parser_cocci_menhir.ml"
+# 14823 "parser_cocci_menhir.ml"
) =
# 180 "parser_cocci_menhir.mly"
( m (!Ast0.rule_name) )
-# 14795 "parser_cocci_menhir.ml"
+# 14827 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaFreshIdDecl(arity,name)) in
!Data.add_id_meta name [] pure; tok) )
-# 14846 "parser_cocci_menhir.ml"
+# 14878 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 14852 "parser_cocci_menhir.ml"
+# 14884 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaParamDecl(arity,name)) in
!Data.add_param_meta name pure; tok) )
-# 14899 "parser_cocci_menhir.ml"
+# 14931 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 14905 "parser_cocci_menhir.ml"
+# 14937 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaParamListDecl(arity,name,None)) in
!Data.add_paramlist_meta name None pure; tok) )
-# 14956 "parser_cocci_menhir.ml"
+# 14988 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 14962 "parser_cocci_menhir.ml"
+# 14994 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaExpListDecl(arity,name,None)) in
!Data.add_explist_meta name None pure; tok) )
-# 15013 "parser_cocci_menhir.ml"
+# 15045 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 15019 "parser_cocci_menhir.ml"
+# 15051 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaTypeDecl(arity,name)) in
!Data.add_type_meta name pure; tok) )
-# 15066 "parser_cocci_menhir.ml"
+# 15098 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 15072 "parser_cocci_menhir.ml"
+# 15104 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
!Data.add_stm_meta name pure; tok) )
-# 15119 "parser_cocci_menhir.ml"
+# 15151 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 15125 "parser_cocci_menhir.ml"
+# 15157 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta ->
let tok = check_meta(Ast.MetaStmListDecl(arity,name)) in
!Data.add_stmlist_meta name pure; tok) )
-# 15176 "parser_cocci_menhir.ml"
+# 15208 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 15182 "parser_cocci_menhir.ml"
+# 15214 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
if arity = Ast.NONE && pure = Ast0.Impure
then (!Data.add_type_name name; [])
else raise (Semantic_cocci.Semantic "bad typedef")) )
-# 15230 "parser_cocci_menhir.ml"
+# 15262 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 15236 "parser_cocci_menhir.ml"
+# 15268 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
if arity = Ast.NONE && pure = Ast0.Impure
then (!Data.add_declarer_name name; [])
else raise (Semantic_cocci.Semantic "bad declarer")) )
-# 15288 "parser_cocci_menhir.ml"
+# 15320 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 15294 "parser_cocci_menhir.ml"
+# 15326 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
if arity = Ast.NONE && pure = Ast0.Impure
then (!Data.add_iterator_name name; [])
else raise (Semantic_cocci.Semantic "bad iterator")) )
-# 15346 "parser_cocci_menhir.ml"
+# 15378 "parser_cocci_menhir.ml"
in
# 253 "parser_cocci_menhir.mly"
( P.create_metadec ar ispure kindfn ids )
-# 15352 "parser_cocci_menhir.ml"
+# 15384 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaIdDecl(arity,name)) in
!Data.add_id_meta name constraints pure; tok) )
-# 15399 "parser_cocci_menhir.ml"
+# 15431 "parser_cocci_menhir.ml"
in
# 257 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15405 "parser_cocci_menhir.ml"
+# 15437 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaFuncDecl(arity,name)) in
!Data.add_func_meta name constraints pure; tok) )
-# 15452 "parser_cocci_menhir.ml"
+# 15484 "parser_cocci_menhir.ml"
in
# 257 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15458 "parser_cocci_menhir.ml"
+# 15490 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let tok = check_meta(Ast.MetaLocalFuncDecl(arity,name)) in
!Data.add_local_func_meta name constraints pure;
tok) )
-# 15510 "parser_cocci_menhir.ml"
+# 15542 "parser_cocci_menhir.ml"
in
# 257 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15516 "parser_cocci_menhir.ml"
+# 15548 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaDeclarerDecl(arity,name)) in
!Data.add_declarer_meta name constraints pure; tok) )
-# 15563 "parser_cocci_menhir.ml"
+# 15595 "parser_cocci_menhir.ml"
in
# 257 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15569 "parser_cocci_menhir.ml"
+# 15601 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaIteratorDecl(arity,name)) in
!Data.add_iterator_meta name constraints pure; tok) )
-# 15616 "parser_cocci_menhir.ml"
+# 15648 "parser_cocci_menhir.ml"
in
# 257 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15622 "parser_cocci_menhir.ml"
+# 15654 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaErrDecl(arity,name)) in
!Data.add_err_meta name constraints pure; tok) )
-# 15669 "parser_cocci_menhir.ml"
+# 15701 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15675 "parser_cocci_menhir.ml"
+# 15707 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 39 "standard.mly"
( None )
-# 15728 "parser_cocci_menhir.ml"
+# 15760 "parser_cocci_menhir.ml"
in
| Some _ ->
!Data.add_local_idexp_meta ty name constraints pure;
check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) )
-# 15741 "parser_cocci_menhir.ml"
+# 15773 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15747 "parser_cocci_menhir.ml"
+# 15779 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 41 "standard.mly"
( Some x )
-# 15808 "parser_cocci_menhir.ml"
+# 15840 "parser_cocci_menhir.ml"
in
| Some _ ->
!Data.add_local_idexp_meta ty name constraints pure;
check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) )
-# 15821 "parser_cocci_menhir.ml"
+# 15853 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15827 "parser_cocci_menhir.ml"
+# 15859 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
| Some _ ->
!Data.add_local_idexp_meta ty name constraints pure;
check_meta(Ast.MetaLocalIdExpDecl(arity,name,ty))) )
-# 15894 "parser_cocci_menhir.ml"
+# 15926 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15900 "parser_cocci_menhir.ml"
+# 15932 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty = Some [P.ty_pointerify Type_cocci.Unknown m] in
let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
!Data.add_exp_meta ty name constraints pure; tok) )
-# 15955 "parser_cocci_menhir.ml"
+# 15987 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 15961 "parser_cocci_menhir.ml"
+# 15993 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let ty = Some (List.map (function x -> Type_cocci.Array x) vl) in
let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
!Data.add_exp_meta ty name constraints pure; tok) )
-# 16020 "parser_cocci_menhir.ml"
+# 16052 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 16026 "parser_cocci_menhir.ml"
+# 16058 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 39 "standard.mly"
( None )
-# 16072 "parser_cocci_menhir.ml"
+# 16104 "parser_cocci_menhir.ml"
in
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
!Data.add_const_meta ty name constraints pure; tok) )
-# 16080 "parser_cocci_menhir.ml"
+# 16112 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 16086 "parser_cocci_menhir.ml"
+# 16118 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 41 "standard.mly"
( Some x )
-# 16140 "parser_cocci_menhir.ml"
+# 16172 "parser_cocci_menhir.ml"
in
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaConstDecl(arity,name,ty)) in
!Data.add_const_meta ty name constraints pure; tok) )
-# 16148 "parser_cocci_menhir.ml"
+# 16180 "parser_cocci_menhir.ml"
in
# 261 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 16154 "parser_cocci_menhir.ml"
+# 16186 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (fun arity name pure check_meta constraints ->
let tok = check_meta(Ast.MetaExpDecl(arity,name,None)) in
!Data.add_exp_meta None name constraints pure; tok) )
-# 16201 "parser_cocci_menhir.ml"
+# 16233 "parser_cocci_menhir.ml"
in
# 265 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 16207 "parser_cocci_menhir.ml"
+# 16239 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
constraints;
let tok = check_meta(Ast.MetaExpDecl(arity,name,ty)) in
!Data.add_exp_meta ty name constraints pure; tok) )
-# 16273 "parser_cocci_menhir.ml"
+# 16305 "parser_cocci_menhir.ml"
in
# 265 "parser_cocci_menhir.mly"
( P.create_metadec_ne ar ispure kindfn ids )
-# 16279 "parser_cocci_menhir.ml"
+# 16311 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let any = match a with None -> Ast.PER | Some _ -> Ast.ALL in
!Data.add_pos_meta name constraints any; tok in
P.create_metadec_ne ar false kindfn ids )
-# 16327 "parser_cocci_menhir.ml"
+# 16359 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
check_meta(Ast.MetaParamListDecl(arity,name,Some lenname)) in
!Data.add_paramlist_meta name (Some lenname) pure; tok)
id ids )
-# 16394 "parser_cocci_menhir.ml"
+# 16426 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
check_meta(Ast.MetaExpListDecl(arity,name,Some lenname)) in
!Data.add_explist_meta name (Some lenname) pure; tok)
id ids )
-# 16461 "parser_cocci_menhir.ml"
+# 16493 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_midzero_list_ctype_ctype_ =
-# 1692 "parser_cocci_menhir.mly"
+# 1698 "parser_cocci_menhir.mly"
( let (mids,code) = List.split b in (mids,(a::code)) )
-# 16491 "parser_cocci_menhir.ml"
+# 16523 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_midzero_list_eexpr_eexpr_ =
-# 1692 "parser_cocci_menhir.mly"
+# 1698 "parser_cocci_menhir.mly"
( let (mids,code) = List.split b in (mids,(a::code)) )
-# 16521 "parser_cocci_menhir.ml"
+# 16553 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_midzero_list_expr_eexpr_ =
-# 1692 "parser_cocci_menhir.mly"
+# 1698 "parser_cocci_menhir.mly"
( let (mids,code) = List.split b in (mids,(a::code)) )
-# 16551 "parser_cocci_menhir.ml"
+# 16583 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_midzero_list_fun_after_stm_fun_after_dots_or_ =
-# 1692 "parser_cocci_menhir.mly"
+# 1698 "parser_cocci_menhir.mly"
( let (mids,code) = List.split b in (mids,(a::code)) )
-# 16581 "parser_cocci_menhir.ml"
+# 16613 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_midzero_list_fun_start_fun_start_ =
-# 1692 "parser_cocci_menhir.mly"
+# 1698 "parser_cocci_menhir.mly"
( let (mids,code) = List.split b in (mids,(a::code)) )
-# 16611 "parser_cocci_menhir.ml"
+# 16643 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_midzero_list_rule_elem_statement_rule_elem_statement_ =
-# 1692 "parser_cocci_menhir.mly"
+# 1698 "parser_cocci_menhir.mly"
( let (mids,code) = List.split b in (mids,(a::code)) )
-# 16641 "parser_cocci_menhir.ml"
+# 16673 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_midzero_list_statement_statement_ =
-# 1692 "parser_cocci_menhir.mly"
+# 1698 "parser_cocci_menhir.mly"
( let (mids,code) = List.split b in (mids,(a::code)) )
-# 16671 "parser_cocci_menhir.ml"
+# 16703 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( match f@b@ew with
[] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
| code -> Top_level.top_level code )
-# 16709 "parser_cocci_menhir.ml"
+# 16741 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( match f@[b]@ew with
[] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
| code -> Top_level.top_level code )
-# 16747 "parser_cocci_menhir.ml"
+# 16779 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 136 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 16775 "parser_cocci_menhir.ml"
+# 16807 "parser_cocci_menhir.ml"
) =
# 176 "parser_cocci_menhir.mly"
( _1 )
-# 16779 "parser_cocci_menhir.ml"
+# 16811 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 136 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 16807 "parser_cocci_menhir.ml"
+# 16839 "parser_cocci_menhir.ml"
) =
# 176 "parser_cocci_menhir.mly"
( m )
-# 16811 "parser_cocci_menhir.ml"
+# 16843 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 136 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 16839 "parser_cocci_menhir.ml"
+# 16871 "parser_cocci_menhir.ml"
) =
# 177 "parser_cocci_menhir.mly"
( m )
-# 16843 "parser_cocci_menhir.ml"
+# 16875 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 133 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 16871 "parser_cocci_menhir.ml"
+# 16903 "parser_cocci_menhir.ml"
) =
# 172 "parser_cocci_menhir.mly"
( _1 )
-# 16875 "parser_cocci_menhir.ml"
+# 16907 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 133 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 16903 "parser_cocci_menhir.ml"
+# 16935 "parser_cocci_menhir.ml"
) =
# 172 "parser_cocci_menhir.mly"
( m )
-# 16907 "parser_cocci_menhir.ml"
+# 16939 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 133 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 16935 "parser_cocci_menhir.ml"
+# 16967 "parser_cocci_menhir.ml"
) =
# 173 "parser_cocci_menhir.mly"
( m )
-# 16939 "parser_cocci_menhir.ml"
+# 16971 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_minus_start =
# 1514 "parser_cocci_menhir.mly"
( [Ast0.wrap(Ast0.DECL(_1))] )
-# 16963 "parser_cocci_menhir.ml"
+# 16995 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_minus_start =
# 1515 "parser_cocci_menhir.mly"
( [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty(_1))))] )
-# 16987 "parser_cocci_menhir.ml"
+# 17019 "parser_cocci_menhir.ml"
+ in
+ _menhir_env.MenhirLib.EngineTypes.stack <- {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = Obj.repr _v;
+ MenhirLib.EngineTypes.startp = _startpos;
+ MenhirLib.EngineTypes.endp = _endpos;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ });
+ (fun _menhir_env ->
+ let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+ let {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = _1;
+ MenhirLib.EngineTypes.startp = _startpos__1_;
+ MenhirLib.EngineTypes.endp = _endpos__1_;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ } = _menhir_stack in
+ let _1 : 'tv_top_init = Obj.magic _1 in
+ let _startpos = _startpos__1_ in
+ let _endpos = _endpos__1_ in
+ let _v : 'tv_minus_start =
+# 1516 "parser_cocci_menhir.mly"
+ ( [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit(_1))))] )
+# 17043 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_minus_start =
-# 1517 "parser_cocci_menhir.mly"
+# 1518 "parser_cocci_menhir.mly"
( List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) _1 )
-# 17011 "parser_cocci_menhir.ml"
+# 17067 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let a : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17038 "parser_cocci_menhir.ml"
+# 17094 "parser_cocci_menhir.ml"
) = Obj.magic a in
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_mzl_ctype_ =
-# 1695 "parser_cocci_menhir.mly"
+# 1701 "parser_cocci_menhir.mly"
( (P.clt2mcode "|" a, b) )
-# 17045 "parser_cocci_menhir.ml"
+# 17101 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let a : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17072 "parser_cocci_menhir.ml"
+# 17128 "parser_cocci_menhir.ml"
) = Obj.magic a in
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_mzl_eexpr_ =
-# 1695 "parser_cocci_menhir.mly"
+# 1701 "parser_cocci_menhir.mly"
( (P.clt2mcode "|" a, b) )
-# 17079 "parser_cocci_menhir.ml"
+# 17135 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let a : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17106 "parser_cocci_menhir.ml"
+# 17162 "parser_cocci_menhir.ml"
) = Obj.magic a in
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_mzl_fun_after_dots_or_ =
-# 1695 "parser_cocci_menhir.mly"
+# 1701 "parser_cocci_menhir.mly"
( (P.clt2mcode "|" a, b) )
-# 17113 "parser_cocci_menhir.ml"
+# 17169 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let a : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17140 "parser_cocci_menhir.ml"
+# 17196 "parser_cocci_menhir.ml"
) = Obj.magic a in
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_mzl_fun_start_ =
-# 1695 "parser_cocci_menhir.mly"
+# 1701 "parser_cocci_menhir.mly"
( (P.clt2mcode "|" a, b) )
-# 17147 "parser_cocci_menhir.ml"
+# 17203 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let a : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17174 "parser_cocci_menhir.ml"
+# 17230 "parser_cocci_menhir.ml"
) = Obj.magic a in
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_mzl_rule_elem_statement_ =
-# 1695 "parser_cocci_menhir.mly"
+# 1701 "parser_cocci_menhir.mly"
( (P.clt2mcode "|" a, b) )
-# 17181 "parser_cocci_menhir.ml"
+# 17237 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let a : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17208 "parser_cocci_menhir.ml"
+# 17264 "parser_cocci_menhir.ml"
) = Obj.magic a in
let _startpos = _startpos_a_ in
let _endpos = _endpos_b_ in
let _v : 'tv_mzl_statement_ =
-# 1695 "parser_cocci_menhir.mly"
+# 1701 "parser_cocci_menhir.mly"
( (P.clt2mcode "|" a, b) )
-# 17215 "parser_cocci_menhir.ml"
+# 17271 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_name_opt_decl =
# 785 "parser_cocci_menhir.mly"
( _1 )
-# 17239 "parser_cocci_menhir.ml"
+# 17295 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_name_opt_decl =
# 786 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Param(t, None)) )
-# 17263 "parser_cocci_menhir.ml"
+# 17319 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17314 "parser_cocci_menhir.ml"
+# 17370 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_decl_list_name_opt_decl_ = Obj.magic d in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 17320 "parser_cocci_menhir.ml"
+# 17376 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 17325 "parser_cocci_menhir.ml"
+# 17381 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let s : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 17330 "parser_cocci_menhir.ml"
+# 17386 "parser_cocci_menhir.ml"
) = Obj.magic s in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 17335 "parser_cocci_menhir.ml"
+# 17391 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let t : 'tv_fn_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
(t,P.clt2mcode "(" lp,P.clt2mcode "*" s,P.clt2mcode ")" rp,
P.clt2mcode "(" lp1,d,P.clt2mcode ")" rp1)) in
Ast0.wrap(Ast0.Param(fnptr, None)) )
-# 17348 "parser_cocci_menhir.ml"
+# 17404 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_nest_after_dots =
-# 1616 "parser_cocci_menhir.mly"
+# 1622 "parser_cocci_menhir.mly"
(_1@_2)
-# 17378 "parser_cocci_menhir.ml"
+# 17434 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_nest_after_dots =
-# 1617 "parser_cocci_menhir.mly"
+# 1623 "parser_cocci_menhir.mly"
(_2)
-# 17406 "parser_cocci_menhir.ml"
+# 17462 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_nest_after_dots =
-# 1618 "parser_cocci_menhir.mly"
+# 1624 "parser_cocci_menhir.mly"
((Ast0.wrap(Ast0.Exp(_1)))::_2)
-# 17436 "parser_cocci_menhir.ml"
+# 17492 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_nest_after_exp =
-# 1626 "parser_cocci_menhir.mly"
+# 1632 "parser_cocci_menhir.mly"
([])
-# 17453 "parser_cocci_menhir.ml"
+# 17509 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_nest_after_exp =
-# 1627 "parser_cocci_menhir.mly"
+# 1633 "parser_cocci_menhir.mly"
(_1::_2)
-# 17483 "parser_cocci_menhir.ml"
+# 17539 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_nest_after_stm =
-# 1621 "parser_cocci_menhir.mly"
+# 1627 "parser_cocci_menhir.mly"
([])
-# 17500 "parser_cocci_menhir.ml"
+# 17556 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_nest_after_stm =
-# 1622 "parser_cocci_menhir.mly"
+# 1628 "parser_cocci_menhir.mly"
(_1::_2)
-# 17530 "parser_cocci_menhir.ml"
+# 17586 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_nest_after_stm =
-# 1623 "parser_cocci_menhir.mly"
+# 1629 "parser_cocci_menhir.mly"
(_1@_2)
-# 17560 "parser_cocci_menhir.ml"
+# 17616 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let c : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 17596 "parser_cocci_menhir.ml"
+# 17652 "parser_cocci_menhir.ml"
) = Obj.magic c in
let e : 'tv_expr_dots_TEllipsis_ = Obj.magic e in
let w : 'tv_option_whenexp_ = Obj.magic w in
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 17603 "parser_cocci_menhir.ml"
+# 17659 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos_c_ in
( Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<..." _1,
Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
P.clt2mcode "...>" c, w, false)) )
-# 17612 "parser_cocci_menhir.ml"
+# 17668 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let c : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 17648 "parser_cocci_menhir.ml"
+# 17704 "parser_cocci_menhir.ml"
) = Obj.magic c in
let e : 'tv_expr_dots_TEllipsis_ = Obj.magic e in
let w : 'tv_option_whenexp_ = Obj.magic w in
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 17655 "parser_cocci_menhir.ml"
+# 17711 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos_c_ in
( Ast0.wrap(Ast0.NestExpr(P.clt2mcode "<+..." _1,
Ast0.wrap(Ast0.DOTS(e (P.mkedots "..."))),
P.clt2mcode "...+>" c, w, true)) )
-# 17664 "parser_cocci_menhir.ml"
+# 17720 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_nest_start =
-# 1613 "parser_cocci_menhir.mly"
+# 1619 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS(_1)) )
-# 17688 "parser_cocci_menhir.ml"
+# 17744 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 167 "parser_cocci_menhir.mly"
(unit)
-# 17710 "parser_cocci_menhir.ml"
+# 17766 "parser_cocci_menhir.ml"
) =
-# 1760 "parser_cocci_menhir.mly"
+# 1764 "parser_cocci_menhir.mly"
( () )
-# 17714 "parser_cocci_menhir.ml"
+# 17770 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 167 "parser_cocci_menhir.mly"
(unit)
-# 17740 "parser_cocci_menhir.ml"
+# 17796 "parser_cocci_menhir.ml"
) =
-# 1761 "parser_cocci_menhir.mly"
+# 1765 "parser_cocci_menhir.mly"
( () )
-# 17744 "parser_cocci_menhir.ml"
+# 17800 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 167 "parser_cocci_menhir.mly"
(unit)
-# 17766 "parser_cocci_menhir.ml"
+# 17822 "parser_cocci_menhir.ml"
) =
-# 1762 "parser_cocci_menhir.mly"
+# 1766 "parser_cocci_menhir.mly"
( () )
-# 17770 "parser_cocci_menhir.ml"
+# 17826 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
# 1316 "parser_cocci_menhir.mly"
( function dot_builder ->
g :: (List.concat(List.map (function (d,g) -> [dot_builder d;g]) dg)) )
-# 17801 "parser_cocci_menhir.ml"
+# 17857 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let x : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 17822 "parser_cocci_menhir.ml"
+# 17878 "parser_cocci_menhir.ml"
) = Obj.magic x in
let _startpos = _startpos_x_ in
let _endpos = _endpos_x_ in
let _v : 'tv_nonempty_list_TMul_ =
# 124 "standard.mly"
( [ x ] )
-# 17829 "parser_cocci_menhir.ml"
+# 17885 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let x : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 17856 "parser_cocci_menhir.ml"
+# 17912 "parser_cocci_menhir.ml"
) = Obj.magic x in
let _startpos = _startpos_x_ in
let _endpos = _endpos_xs_ in
let _v : 'tv_nonempty_list_TMul_ =
# 126 "standard.mly"
( x :: xs )
-# 17863 "parser_cocci_menhir.ml"
+# 17919 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (if !Data.in_iso
then failwith "constraints not allowed in iso file");
[i] )
-# 17893 "parser_cocci_menhir.ml"
+# 17949 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (if !Data.in_iso
then failwith "constraints not allowed in iso file");
l )
-# 17931 "parser_cocci_menhir.ml"
+# 17987 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (if !Data.in_iso
then failwith "constraints not allowed in iso file");
[Ast0.wrap(Ast0.Id(P.id2mcode i))] )
-# 17961 "parser_cocci_menhir.ml"
+# 18017 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (if !Data.in_iso
then failwith "constraints not allowed in iso file");
List.map (function i -> Ast0.wrap(Ast0.Id(P.id2mcode i))) l )
-# 17999 "parser_cocci_menhir.ml"
+# 18055 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
( (if !Data.in_iso
then failwith "constraints not allowed in iso file");
[Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i))))] )
-# 18029 "parser_cocci_menhir.ml"
+# 18085 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
(function i ->
Ast0.wrap(Ast0.Ident(Ast0.wrap(Ast0.Id(P.id2mcode i)))))
l )
-# 18070 "parser_cocci_menhir.ml"
+# 18126 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let i = (rule,name) in
P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
[i] )
-# 18105 "parser_cocci_menhir.ml"
+# 18161 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
P.check_meta(Ast.MetaPosDecl(Ast.NONE,i));
i)
l )
-# 18151 "parser_cocci_menhir.ml"
+# 18207 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_one_dec_decl_ =
# 1458 "parser_cocci_menhir.mly"
( _1 )
-# 18175 "parser_cocci_menhir.ml"
+# 18231 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 65 "parser_cocci_menhir.mly"
(Parse_aux.list_info)
-# 18196 "parser_cocci_menhir.ml"
+# 18252 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
Some nm -> Some(P.clt2mcode nm clt)
| None -> None in
Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) )
-# 18209 "parser_cocci_menhir.ml"
+# 18265 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_one_dec_name_opt_decl_ =
# 1458 "parser_cocci_menhir.mly"
( _1 )
-# 18233 "parser_cocci_menhir.ml"
+# 18289 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 65 "parser_cocci_menhir.mly"
(Parse_aux.list_info)
-# 18254 "parser_cocci_menhir.ml"
+# 18310 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
Some nm -> Some(P.clt2mcode nm clt)
| None -> None in
Ast0.wrap(Ast0.MetaParamList(nm,lenname,pure)) )
-# 18267 "parser_cocci_menhir.ml"
+# 18323 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18293 "parser_cocci_menhir.ml"
+# 18349 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let t : 'tv_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
let _v : 'tv_one_decl_var =
# 944 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.TyDecl(t,P.clt2mcode ";" pv)) )
-# 18301 "parser_cocci_menhir.ml"
+# 18357 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18332 "parser_cocci_menhir.ml"
+# 18388 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 39 "standard.mly"
( None )
-# 18342 "parser_cocci_menhir.ml"
+# 18398 "parser_cocci_menhir.ml"
in
# 946 "parser_cocci_menhir.mly"
( let (id,fn) = d in
Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) )
-# 18349 "parser_cocci_menhir.ml"
+# 18405 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18385 "parser_cocci_menhir.ml"
+# 18441 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 41 "standard.mly"
( Some x )
-# 18397 "parser_cocci_menhir.ml"
+# 18453 "parser_cocci_menhir.ml"
in
# 946 "parser_cocci_menhir.mly"
( let (id,fn) = d in
Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) )
-# 18404 "parser_cocci_menhir.ml"
+# 18460 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_one_decl_var =
# 948 "parser_cocci_menhir.mly"
( f )
-# 18428 "parser_cocci_menhir.ml"
+# 18484 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18469 "parser_cocci_menhir.ml"
+# 18525 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18475 "parser_cocci_menhir.ml"
+# 18531 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 39 "standard.mly"
( None )
-# 18485 "parser_cocci_menhir.ml"
+# 18541 "parser_cocci_menhir.ml"
in
# 950 "parser_cocci_menhir.mly"
( let (id,fn) = d in
Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) )
-# 18492 "parser_cocci_menhir.ml"
+# 18548 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18538 "parser_cocci_menhir.ml"
+# 18594 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18544 "parser_cocci_menhir.ml"
+# 18600 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 41 "standard.mly"
( Some x )
-# 18556 "parser_cocci_menhir.ml"
+# 18612 "parser_cocci_menhir.ml"
in
# 950 "parser_cocci_menhir.mly"
( let (id,fn) = d in
Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)) )
-# 18563 "parser_cocci_menhir.ml"
+# 18619 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18594 "parser_cocci_menhir.ml"
+# 18650 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 18604 "parser_cocci_menhir.ml"
+# 18660 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 18611 "parser_cocci_menhir.ml"
+# 18667 "parser_cocci_menhir.ml"
in
( let (id,fn) = d in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) )
-# 18619 "parser_cocci_menhir.ml"
+# 18675 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18655 "parser_cocci_menhir.ml"
+# 18711 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 18667 "parser_cocci_menhir.ml"
+# 18723 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 18674 "parser_cocci_menhir.ml"
+# 18730 "parser_cocci_menhir.ml"
in
( let (id,fn) = d in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) )
-# 18682 "parser_cocci_menhir.ml"
+# 18738 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18718 "parser_cocci_menhir.ml"
+# 18774 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 18729 "parser_cocci_menhir.ml"
+# 18785 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 18737 "parser_cocci_menhir.ml"
+# 18793 "parser_cocci_menhir.ml"
in
( let (id,fn) = d in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) )
-# 18745 "parser_cocci_menhir.ml"
+# 18801 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18786 "parser_cocci_menhir.ml"
+# 18842 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 18799 "parser_cocci_menhir.ml"
+# 18855 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 18807 "parser_cocci_menhir.ml"
+# 18863 "parser_cocci_menhir.ml"
in
( let (id,fn) = d in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.UnInit(s,fn idtype,id,P.clt2mcode ";" pv)) )
-# 18815 "parser_cocci_menhir.ml"
+# 18871 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18856 "parser_cocci_menhir.ml"
+# 18912 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18862 "parser_cocci_menhir.ml"
+# 18918 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 18872 "parser_cocci_menhir.ml"
+# 18928 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 18879 "parser_cocci_menhir.ml"
+# 18935 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv)) )
-# 18889 "parser_cocci_menhir.ml"
+# 18945 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18935 "parser_cocci_menhir.ml"
+# 18991 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 18941 "parser_cocci_menhir.ml"
+# 18997 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 18953 "parser_cocci_menhir.ml"
+# 19009 "parser_cocci_menhir.ml"
in
let s =
# 39 "standard.mly"
( None )
-# 18960 "parser_cocci_menhir.ml"
+# 19016 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv)) )
-# 18970 "parser_cocci_menhir.ml"
+# 19026 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19016 "parser_cocci_menhir.ml"
+# 19072 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19022 "parser_cocci_menhir.ml"
+# 19078 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 19033 "parser_cocci_menhir.ml"
+# 19089 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 19041 "parser_cocci_menhir.ml"
+# 19097 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv)) )
-# 19051 "parser_cocci_menhir.ml"
+# 19107 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19102 "parser_cocci_menhir.ml"
+# 19158 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19108 "parser_cocci_menhir.ml"
+# 19164 "parser_cocci_menhir.ml"
) = Obj.magic q in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 19121 "parser_cocci_menhir.ml"
+# 19177 "parser_cocci_menhir.ml"
in
let s =
# 41 "standard.mly"
( Some x )
-# 19129 "parser_cocci_menhir.ml"
+# 19185 "parser_cocci_menhir.ml"
in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
Ast0.wrap(Ast0.Init(s,fn idtype,id,P.clt2mcode "=" q,e,
P.clt2mcode ";" pv)) )
-# 19139 "parser_cocci_menhir.ml"
+# 19195 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19200 "parser_cocci_menhir.ml"
+# 19256 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19205 "parser_cocci_menhir.ml"
+# 19261 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19211 "parser_cocci_menhir.ml"
+# 19267 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19216 "parser_cocci_menhir.ml"
+# 19272 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 19222 "parser_cocci_menhir.ml"
+# 19278 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19227 "parser_cocci_menhir.ml"
+# 19283 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
# 39 "standard.mly"
( None )
-# 19236 "parser_cocci_menhir.ml"
+# 19292 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) )
-# 19248 "parser_cocci_menhir.ml"
+# 19304 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19314 "parser_cocci_menhir.ml"
+# 19370 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19319 "parser_cocci_menhir.ml"
+# 19375 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19325 "parser_cocci_menhir.ml"
+# 19381 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19330 "parser_cocci_menhir.ml"
+# 19386 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 19336 "parser_cocci_menhir.ml"
+# 19392 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19341 "parser_cocci_menhir.ml"
+# 19397 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let x0 : 'tv_storage = Obj.magic x0 in
# 41 "standard.mly"
( Some x )
-# 19352 "parser_cocci_menhir.ml"
+# 19408 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
Ast0.wrap(Ast0.UnInit(s,fn t,id,P.clt2mcode ";" pv)) )
-# 19364 "parser_cocci_menhir.ml"
+# 19420 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _5 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19405 "parser_cocci_menhir.ml"
+# 19461 "parser_cocci_menhir.ml"
) = Obj.magic _5 in
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19410 "parser_cocci_menhir.ml"
+# 19466 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr_list_option = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19416 "parser_cocci_menhir.ml"
+# 19472 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_decl_ident = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 978 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.MacroDecl(_1,P.clt2mcode "(" _2,_3,
P.clt2mcode ")" _4,P.clt2mcode ";" _5)) )
-# 19425 "parser_cocci_menhir.ml"
+# 19481 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19496 "parser_cocci_menhir.ml"
+# 19552 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19502 "parser_cocci_menhir.ml"
+# 19558 "parser_cocci_menhir.ml"
) = Obj.magic q in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19507 "parser_cocci_menhir.ml"
+# 19563 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19513 "parser_cocci_menhir.ml"
+# 19569 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19518 "parser_cocci_menhir.ml"
+# 19574 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 19524 "parser_cocci_menhir.ml"
+# 19580 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19529 "parser_cocci_menhir.ml"
+# 19585 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
# 39 "standard.mly"
( None )
-# 19538 "parser_cocci_menhir.ml"
+# 19594 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)))
-# 19550 "parser_cocci_menhir.ml"
+# 19606 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19626 "parser_cocci_menhir.ml"
+# 19682 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let e : 'tv_initialize = Obj.magic e in
let q : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 19632 "parser_cocci_menhir.ml"
+# 19688 "parser_cocci_menhir.ml"
) = Obj.magic q in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19637 "parser_cocci_menhir.ml"
+# 19693 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19643 "parser_cocci_menhir.ml"
+# 19699 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 19648 "parser_cocci_menhir.ml"
+# 19704 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 19654 "parser_cocci_menhir.ml"
+# 19710 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 19659 "parser_cocci_menhir.ml"
+# 19715 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let x0 : 'tv_storage = Obj.magic x0 in
# 41 "standard.mly"
( Some x )
-# 19670 "parser_cocci_menhir.ml"
+# 19726 "parser_cocci_menhir.ml"
in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
Ast0.wrap(Ast0.Init(s,fn t,id,P.clt2mcode "=" q,e,P.clt2mcode ";" pv)))
-# 19682 "parser_cocci_menhir.ml"
+# 19738 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_TLocal_ =
# 29 "standard.mly"
( None )
-# 19699 "parser_cocci_menhir.ml"
+# 19755 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_TLocal_ =
# 31 "standard.mly"
( Some x )
-# 19723 "parser_cocci_menhir.ml"
+# 19779 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_TPosAny_ =
# 29 "standard.mly"
( None )
-# 19740 "parser_cocci_menhir.ml"
+# 19796 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_TPosAny_ =
# 31 "standard.mly"
( Some x )
-# 19764 "parser_cocci_menhir.ml"
+# 19820 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_eexpr_ =
# 29 "standard.mly"
( None )
-# 19781 "parser_cocci_menhir.ml"
+# 19837 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_eexpr_ =
# 31 "standard.mly"
( Some x )
-# 19805 "parser_cocci_menhir.ml"
+# 19861 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_whenexp_ =
# 29 "standard.mly"
( None )
-# 19822 "parser_cocci_menhir.ml"
+# 19878 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_option_whenexp_ =
# 31 "standard.mly"
( Some x )
-# 19846 "parser_cocci_menhir.ml"
+# 19902 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_plus_after_dots =
-# 1563 "parser_cocci_menhir.mly"
+# 1569 "parser_cocci_menhir.mly"
([])
-# 19863 "parser_cocci_menhir.ml"
+# 19919 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_dots =
-# 1564 "parser_cocci_menhir.mly"
+# 1570 "parser_cocci_menhir.mly"
(_2)
-# 19891 "parser_cocci_menhir.ml"
+# 19947 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_dots =
-# 1566 "parser_cocci_menhir.mly"
+# 1572 "parser_cocci_menhir.mly"
( (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp(_1)))))::_2 )
-# 19921 "parser_cocci_menhir.ml"
+# 19977 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_dots =
-# 1567 "parser_cocci_menhir.mly"
+# 1573 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DECL(_1))::_2 )
-# 19951 "parser_cocci_menhir.ml"
+# 20007 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_dots =
-# 1569 "parser_cocci_menhir.mly"
+# 1575 "parser_cocci_menhir.mly"
( (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) _1)@_2 )
-# 19981 "parser_cocci_menhir.ml"
+# 20037 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_plus_after_exp =
-# 1559 "parser_cocci_menhir.mly"
+# 1565 "parser_cocci_menhir.mly"
([])
-# 19998 "parser_cocci_menhir.ml"
+# 20054 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_exp =
-# 1560 "parser_cocci_menhir.mly"
+# 1566 "parser_cocci_menhir.mly"
( (Ast0.wrap(Ast0.OTHER(_1)))::_2 )
-# 20028 "parser_cocci_menhir.ml"
+# 20084 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_plus_after_stm =
-# 1572 "parser_cocci_menhir.mly"
+# 1578 "parser_cocci_menhir.mly"
([])
-# 20045 "parser_cocci_menhir.ml"
+# 20101 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_stm =
-# 1573 "parser_cocci_menhir.mly"
+# 1579 "parser_cocci_menhir.mly"
( (Ast0.wrap(Ast0.OTHER(_1)))::_2 )
-# 20075 "parser_cocci_menhir.ml"
+# 20131 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_stm =
-# 1574 "parser_cocci_menhir.mly"
+# 1580 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DECL(_1))::_2 )
-# 20105 "parser_cocci_menhir.ml"
+# 20161 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_after_stm =
-# 1576 "parser_cocci_menhir.mly"
+# 1582 "parser_cocci_menhir.mly"
( (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) _1)@_2 )
-# 20135 "parser_cocci_menhir.ml"
+# 20191 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_plus_body =
# 562 "parser_cocci_menhir.mly"
( Top_level.top_level (f@b@ew) )
-# 20171 "parser_cocci_menhir.ml"
+# 20227 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_plus_exp_body =
# 576 "parser_cocci_menhir.mly"
( Top_level.top_level (f@[b]@ew) )
-# 20207 "parser_cocci_menhir.ml"
+# 20263 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 142 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 20235 "parser_cocci_menhir.ml"
+# 20291 "parser_cocci_menhir.ml"
) =
# 178 "parser_cocci_menhir.mly"
( _1 )
-# 20239 "parser_cocci_menhir.ml"
+# 20295 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 142 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 20267 "parser_cocci_menhir.ml"
+# 20323 "parser_cocci_menhir.ml"
) =
# 178 "parser_cocci_menhir.mly"
( p )
-# 20271 "parser_cocci_menhir.ml"
+# 20327 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 142 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 20299 "parser_cocci_menhir.ml"
+# 20355 "parser_cocci_menhir.ml"
) =
# 179 "parser_cocci_menhir.mly"
( p )
-# 20303 "parser_cocci_menhir.ml"
+# 20359 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 139 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 20331 "parser_cocci_menhir.ml"
+# 20387 "parser_cocci_menhir.ml"
) =
# 174 "parser_cocci_menhir.mly"
( _1 )
-# 20335 "parser_cocci_menhir.ml"
+# 20391 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 139 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 20363 "parser_cocci_menhir.ml"
+# 20419 "parser_cocci_menhir.ml"
) =
# 174 "parser_cocci_menhir.mly"
( p )
-# 20367 "parser_cocci_menhir.ml"
+# 20423 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 139 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 20395 "parser_cocci_menhir.ml"
+# 20451 "parser_cocci_menhir.ml"
) =
# 175 "parser_cocci_menhir.mly"
( p )
-# 20399 "parser_cocci_menhir.ml"
+# 20455 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_plus_start =
-# 1549 "parser_cocci_menhir.mly"
+# 1554 "parser_cocci_menhir.mly"
( [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty(_1))))] )
-# 20423 "parser_cocci_menhir.ml"
+# 20479 "parser_cocci_menhir.ml"
+ in
+ _menhir_env.MenhirLib.EngineTypes.stack <- {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = Obj.repr _v;
+ MenhirLib.EngineTypes.startp = _startpos;
+ MenhirLib.EngineTypes.endp = _endpos;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ });
+ (fun _menhir_env ->
+ let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+ let {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = _1;
+ MenhirLib.EngineTypes.startp = _startpos__1_;
+ MenhirLib.EngineTypes.endp = _endpos__1_;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ } = _menhir_stack in
+ let _1 : 'tv_top_init = Obj.magic _1 in
+ let _startpos = _startpos__1_ in
+ let _endpos = _endpos__1_ in
+ let _v : 'tv_plus_start =
+# 1555 "parser_cocci_menhir.mly"
+ ( [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit(_1))))] )
+# 20503 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_start =
-# 1551 "parser_cocci_menhir.mly"
+# 1557 "parser_cocci_menhir.mly"
( (Ast0.wrap(Ast0.OTHER(_1)))::_2 )
-# 20453 "parser_cocci_menhir.ml"
+# 20533 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_start =
-# 1553 "parser_cocci_menhir.mly"
+# 1559 "parser_cocci_menhir.mly"
( (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp(_1)))))::_2 )
-# 20483 "parser_cocci_menhir.ml"
+# 20563 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_start =
-# 1554 "parser_cocci_menhir.mly"
+# 1560 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DECL(_1))::_2 )
-# 20513 "parser_cocci_menhir.ml"
+# 20593 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_plus_start =
-# 1556 "parser_cocci_menhir.mly"
+# 1562 "parser_cocci_menhir.mly"
( (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) _1)@_2 )
-# 20543 "parser_cocci_menhir.ml"
+# 20623 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 20564 "parser_cocci_menhir.ml"
+# 20644 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_pnrule =
# 220 "parser_cocci_menhir.mly"
( Ast.Dep _1 )
-# 20571 "parser_cocci_menhir.ml"
+# 20651 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 20596 "parser_cocci_menhir.ml"
+# 20676 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_pnrule =
# 221 "parser_cocci_menhir.mly"
( Ast.AntiDep _2 )
-# 20603 "parser_cocci_menhir.ml"
+# 20683 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 20628 "parser_cocci_menhir.ml"
+# 20708 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_pnrule =
# 222 "parser_cocci_menhir.mly"
( Ast.EverDep _2 )
-# 20635 "parser_cocci_menhir.ml"
+# 20715 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 20660 "parser_cocci_menhir.ml"
+# 20740 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_pnrule =
# 223 "parser_cocci_menhir.mly"
( Ast.NeverDep _2 )
-# 20667 "parser_cocci_menhir.ml"
+# 20747 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pnrule =
# 224 "parser_cocci_menhir.mly"
( _2 )
-# 20699 "parser_cocci_menhir.ml"
+# 20779 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_postfix_expr_eexpr_dot_expressions_ =
# 1249 "parser_cocci_menhir.mly"
( _1 )
-# 20723 "parser_cocci_menhir.ml"
+# 20803 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 20759 "parser_cocci_menhir.ml"
+# 20839 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 20765 "parser_cocci_menhir.ml"
+# 20845 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1251 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.ArrayAccess (_1,P.clt2mcode "[" _2,_3,
P.clt2mcode "]" _4)) )
-# 20774 "parser_cocci_menhir.ml"
+# 20854 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 20806 "parser_cocci_menhir.ml"
+# 20886 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_dot_expressions_ =
# 1254 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordAccess(_1, P.clt2mcode "." _2, _3)) )
-# 20814 "parser_cocci_menhir.ml"
+# 20894 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 103 "parser_cocci_menhir.mly"
(Data.clt)
-# 20846 "parser_cocci_menhir.ml"
+# 20926 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1256 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordPtAccess(_1, P.clt2mcode "->" _2,
_3)) )
-# 20855 "parser_cocci_menhir.ml"
+# 20935 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 20881 "parser_cocci_menhir.ml"
+# 20961 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_dot_expressions_ =
# 1259 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Inc _2)) )
-# 20889 "parser_cocci_menhir.ml"
+# 20969 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 20915 "parser_cocci_menhir.ml"
+# 20995 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_dot_expressions_ =
# 1261 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Dec _2)) )
-# 20923 "parser_cocci_menhir.ml"
+# 21003 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 20959 "parser_cocci_menhir.ml"
+# 21039 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr_list_option = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 20965 "parser_cocci_menhir.ml"
+# 21045 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_dot_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap(Ast0.FunCall(_1,P.clt2mcode "(" _2,
_3,
P.clt2mcode ")" _4)) )
-# 20975 "parser_cocci_menhir.ml"
+# 21055 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_postfix_expr_eexpr_invalid_ =
# 1249 "parser_cocci_menhir.mly"
( _1 )
-# 20999 "parser_cocci_menhir.ml"
+# 21079 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 21035 "parser_cocci_menhir.ml"
+# 21115 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 21041 "parser_cocci_menhir.ml"
+# 21121 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1251 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.ArrayAccess (_1,P.clt2mcode "[" _2,_3,
P.clt2mcode "]" _4)) )
-# 21050 "parser_cocci_menhir.ml"
+# 21130 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 21082 "parser_cocci_menhir.ml"
+# 21162 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_invalid_ =
# 1254 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordAccess(_1, P.clt2mcode "." _2, _3)) )
-# 21090 "parser_cocci_menhir.ml"
+# 21170 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 103 "parser_cocci_menhir.mly"
(Data.clt)
-# 21122 "parser_cocci_menhir.ml"
+# 21202 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1256 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordPtAccess(_1, P.clt2mcode "->" _2,
_3)) )
-# 21131 "parser_cocci_menhir.ml"
+# 21211 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 21157 "parser_cocci_menhir.ml"
+# 21237 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_invalid_ =
# 1259 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Inc _2)) )
-# 21165 "parser_cocci_menhir.ml"
+# 21245 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 21191 "parser_cocci_menhir.ml"
+# 21271 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_invalid_ =
# 1261 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Dec _2)) )
-# 21199 "parser_cocci_menhir.ml"
+# 21279 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 21235 "parser_cocci_menhir.ml"
+# 21315 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr_list_option = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 21241 "parser_cocci_menhir.ml"
+# 21321 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap(Ast0.FunCall(_1,P.clt2mcode "(" _2,
_3,
P.clt2mcode ")" _4)) )
-# 21251 "parser_cocci_menhir.ml"
+# 21331 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_postfix_expr_eexpr_nest_expressions_ =
# 1249 "parser_cocci_menhir.mly"
( _1 )
-# 21275 "parser_cocci_menhir.ml"
+# 21355 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 21311 "parser_cocci_menhir.ml"
+# 21391 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 21317 "parser_cocci_menhir.ml"
+# 21397 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1251 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.ArrayAccess (_1,P.clt2mcode "[" _2,_3,
P.clt2mcode "]" _4)) )
-# 21326 "parser_cocci_menhir.ml"
+# 21406 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 21358 "parser_cocci_menhir.ml"
+# 21438 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_nest_expressions_ =
# 1254 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordAccess(_1, P.clt2mcode "." _2, _3)) )
-# 21366 "parser_cocci_menhir.ml"
+# 21446 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 103 "parser_cocci_menhir.mly"
(Data.clt)
-# 21398 "parser_cocci_menhir.ml"
+# 21478 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1256 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordPtAccess(_1, P.clt2mcode "->" _2,
_3)) )
-# 21407 "parser_cocci_menhir.ml"
+# 21487 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 21433 "parser_cocci_menhir.ml"
+# 21513 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_nest_expressions_ =
# 1259 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Inc _2)) )
-# 21441 "parser_cocci_menhir.ml"
+# 21521 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 21467 "parser_cocci_menhir.ml"
+# 21547 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_eexpr_nest_expressions_ =
# 1261 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Dec _2)) )
-# 21475 "parser_cocci_menhir.ml"
+# 21555 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 21511 "parser_cocci_menhir.ml"
+# 21591 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr_list_option = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 21517 "parser_cocci_menhir.ml"
+# 21597 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_eexpr_nest_expressions_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap(Ast0.FunCall(_1,P.clt2mcode "(" _2,
_3,
P.clt2mcode ")" _4)) )
-# 21527 "parser_cocci_menhir.ml"
+# 21607 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_postfix_expr_expr_invalid_ =
# 1249 "parser_cocci_menhir.mly"
( _1 )
-# 21551 "parser_cocci_menhir.ml"
+# 21631 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 21587 "parser_cocci_menhir.ml"
+# 21667 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 101 "parser_cocci_menhir.mly"
(Data.clt)
-# 21593 "parser_cocci_menhir.ml"
+# 21673 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1251 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.ArrayAccess (_1,P.clt2mcode "[" _2,_3,
P.clt2mcode "]" _4)) )
-# 21602 "parser_cocci_menhir.ml"
+# 21682 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 21634 "parser_cocci_menhir.ml"
+# 21714 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_expr_invalid_ =
# 1254 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordAccess(_1, P.clt2mcode "." _2, _3)) )
-# 21642 "parser_cocci_menhir.ml"
+# 21722 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 103 "parser_cocci_menhir.mly"
(Data.clt)
-# 21674 "parser_cocci_menhir.ml"
+# 21754 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
# 1256 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.RecordPtAccess(_1, P.clt2mcode "->" _2,
_3)) )
-# 21683 "parser_cocci_menhir.ml"
+# 21763 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 21709 "parser_cocci_menhir.ml"
+# 21789 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_expr_invalid_ =
# 1259 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Inc _2)) )
-# 21717 "parser_cocci_menhir.ml"
+# 21797 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 21743 "parser_cocci_menhir.ml"
+# 21823 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_postfix_expr_expr_invalid_ =
# 1261 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Postfix (_1, P.clt2mcode Ast.Dec _2)) )
-# 21751 "parser_cocci_menhir.ml"
+# 21831 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 21787 "parser_cocci_menhir.ml"
+# 21867 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr_list_option = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 21793 "parser_cocci_menhir.ml"
+# 21873 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_postfix_expr_expr_invalid_ = Obj.magic _1 in
let _startpos = _startpos__1_ in
( Ast0.wrap(Ast0.FunCall(_1,P.clt2mcode "(" _2,
_3,
P.clt2mcode ")" _4)) )
-# 21803 "parser_cocci_menhir.ml"
+# 21883 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_eexpr_dot_expressions_ =
# 1268 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Ident(_1)) )
-# 21827 "parser_cocci_menhir.ml"
+# 21907 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 21848 "parser_cocci_menhir.ml"
+# 21928 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1270 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) )
-# 21856 "parser_cocci_menhir.ml"
+# 21936 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 21877 "parser_cocci_menhir.ml"
+# 21957 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1273 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) )
-# 21885 "parser_cocci_menhir.ml"
+# 21965 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 21906 "parser_cocci_menhir.ml"
+# 21986 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1276 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) )
-# 21914 "parser_cocci_menhir.ml"
+# 21994 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 21935 "parser_cocci_menhir.ml"
+# 22015 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1279 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) )
-# 21943 "parser_cocci_menhir.ml"
+# 22023 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 21964 "parser_cocci_menhir.ml"
+# 22044 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) )
-# 21973 "parser_cocci_menhir.ml"
+# 22053 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 63 "parser_cocci_menhir.mly"
(Parse_aux.expinfo)
-# 21994 "parser_cocci_menhir.ml"
+# 22074 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1286 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) )
-# 22002 "parser_cocci_menhir.ml"
+# 22082 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22023 "parser_cocci_menhir.ml"
+# 22103 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) )
-# 22032 "parser_cocci_menhir.ml"
+# 22112 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22053 "parser_cocci_menhir.ml"
+# 22133 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) )
-# 22062 "parser_cocci_menhir.ml"
+# 22142 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22083 "parser_cocci_menhir.ml"
+# 22163 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) )
-# 22092 "parser_cocci_menhir.ml"
+# 22172 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 22123 "parser_cocci_menhir.ml"
+# 22203 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 22129 "parser_cocci_menhir.ml"
+# 22209 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
# 1301 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Paren(P.clt2mcode "(" _1,_2,
P.clt2mcode ")" _3)) )
-# 22137 "parser_cocci_menhir.ml"
+# 22217 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 22168 "parser_cocci_menhir.ml"
+# 22248 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_midzero_list_eexpr_eexpr_ = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 22174 "parser_cocci_menhir.ml"
+# 22254 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" _1,
code, mids,
P.clt2mcode ")" _3)) )
-# 22184 "parser_cocci_menhir.ml"
+# 22264 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_eexpr_dot_expressions_ =
# 1308 "parser_cocci_menhir.mly"
( _1 )
-# 22208 "parser_cocci_menhir.ml"
+# 22288 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_eexpr_invalid_ =
# 1268 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Ident(_1)) )
-# 22232 "parser_cocci_menhir.ml"
+# 22312 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22253 "parser_cocci_menhir.ml"
+# 22333 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1270 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) )
-# 22261 "parser_cocci_menhir.ml"
+# 22341 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22282 "parser_cocci_menhir.ml"
+# 22362 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1273 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) )
-# 22290 "parser_cocci_menhir.ml"
+# 22370 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22311 "parser_cocci_menhir.ml"
+# 22391 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1276 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) )
-# 22319 "parser_cocci_menhir.ml"
+# 22399 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22340 "parser_cocci_menhir.ml"
+# 22420 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1279 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) )
-# 22348 "parser_cocci_menhir.ml"
+# 22428 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22369 "parser_cocci_menhir.ml"
+# 22449 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) )
-# 22378 "parser_cocci_menhir.ml"
+# 22458 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 63 "parser_cocci_menhir.mly"
(Parse_aux.expinfo)
-# 22399 "parser_cocci_menhir.ml"
+# 22479 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1286 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) )
-# 22407 "parser_cocci_menhir.ml"
+# 22487 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22428 "parser_cocci_menhir.ml"
+# 22508 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) )
-# 22437 "parser_cocci_menhir.ml"
+# 22517 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22458 "parser_cocci_menhir.ml"
+# 22538 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) )
-# 22467 "parser_cocci_menhir.ml"
+# 22547 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22488 "parser_cocci_menhir.ml"
+# 22568 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) )
-# 22497 "parser_cocci_menhir.ml"
+# 22577 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 22528 "parser_cocci_menhir.ml"
+# 22608 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 22534 "parser_cocci_menhir.ml"
+# 22614 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
# 1301 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Paren(P.clt2mcode "(" _1,_2,
P.clt2mcode ")" _3)) )
-# 22542 "parser_cocci_menhir.ml"
+# 22622 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 22573 "parser_cocci_menhir.ml"
+# 22653 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_midzero_list_eexpr_eexpr_ = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 22579 "parser_cocci_menhir.ml"
+# 22659 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" _1,
code, mids,
P.clt2mcode ")" _3)) )
-# 22589 "parser_cocci_menhir.ml"
+# 22669 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_eexpr_invalid_ =
# 1308 "parser_cocci_menhir.mly"
( _1 )
-# 22613 "parser_cocci_menhir.ml"
+# 22693 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_eexpr_nest_expressions_ =
# 1268 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Ident(_1)) )
-# 22637 "parser_cocci_menhir.ml"
+# 22717 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22658 "parser_cocci_menhir.ml"
+# 22738 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1270 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) )
-# 22666 "parser_cocci_menhir.ml"
+# 22746 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22687 "parser_cocci_menhir.ml"
+# 22767 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1273 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) )
-# 22695 "parser_cocci_menhir.ml"
+# 22775 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22716 "parser_cocci_menhir.ml"
+# 22796 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1276 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) )
-# 22724 "parser_cocci_menhir.ml"
+# 22804 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 22745 "parser_cocci_menhir.ml"
+# 22825 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1279 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) )
-# 22753 "parser_cocci_menhir.ml"
+# 22833 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22774 "parser_cocci_menhir.ml"
+# 22854 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) )
-# 22783 "parser_cocci_menhir.ml"
+# 22863 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 63 "parser_cocci_menhir.mly"
(Parse_aux.expinfo)
-# 22804 "parser_cocci_menhir.ml"
+# 22884 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1286 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) )
-# 22812 "parser_cocci_menhir.ml"
+# 22892 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22833 "parser_cocci_menhir.ml"
+# 22913 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) )
-# 22842 "parser_cocci_menhir.ml"
+# 22922 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22863 "parser_cocci_menhir.ml"
+# 22943 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) )
-# 22872 "parser_cocci_menhir.ml"
+# 22952 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 22893 "parser_cocci_menhir.ml"
+# 22973 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) )
-# 22902 "parser_cocci_menhir.ml"
+# 22982 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 22933 "parser_cocci_menhir.ml"
+# 23013 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 22939 "parser_cocci_menhir.ml"
+# 23019 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
# 1301 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Paren(P.clt2mcode "(" _1,_2,
P.clt2mcode ")" _3)) )
-# 22947 "parser_cocci_menhir.ml"
+# 23027 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 22978 "parser_cocci_menhir.ml"
+# 23058 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_midzero_list_eexpr_eexpr_ = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 22984 "parser_cocci_menhir.ml"
+# 23064 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" _1,
code, mids,
P.clt2mcode ")" _3)) )
-# 22994 "parser_cocci_menhir.ml"
+# 23074 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_eexpr_nest_expressions_ =
# 1308 "parser_cocci_menhir.mly"
( _1 )
-# 23018 "parser_cocci_menhir.ml"
+# 23098 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_expr_invalid_ =
# 1268 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Ident(_1)) )
-# 23042 "parser_cocci_menhir.ml"
+# 23122 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 23063 "parser_cocci_menhir.ml"
+# 23143 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1270 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) )
-# 23071 "parser_cocci_menhir.ml"
+# 23151 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 23092 "parser_cocci_menhir.ml"
+# 23172 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1273 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Float x) clt)) )
-# 23100 "parser_cocci_menhir.ml"
+# 23180 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 23121 "parser_cocci_menhir.ml"
+# 23201 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1276 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.String x) clt)) )
-# 23129 "parser_cocci_menhir.ml"
+# 23209 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 23150 "parser_cocci_menhir.ml"
+# 23230 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1279 "parser_cocci_menhir.mly"
( let (x,clt) = _1 in
Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Char x) clt)) )
-# 23158 "parser_cocci_menhir.ml"
+# 23238 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 23179 "parser_cocci_menhir.ml"
+# 23259 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.CONST,pure)) )
-# 23188 "parser_cocci_menhir.ml"
+# 23268 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 63 "parser_cocci_menhir.mly"
(Parse_aux.expinfo)
-# 23209 "parser_cocci_menhir.ml"
+# 23289 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1286 "parser_cocci_menhir.mly"
( let (nm,constraints,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaErr(P.clt2mcode nm clt,constraints,pure)) )
-# 23217 "parser_cocci_menhir.ml"
+# 23297 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 23238 "parser_cocci_menhir.ml"
+# 23318 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ANY,pure)) )
-# 23247 "parser_cocci_menhir.ml"
+# 23327 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 23268 "parser_cocci_menhir.ml"
+# 23348 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.ID,pure)) )
-# 23277 "parser_cocci_menhir.ml"
+# 23357 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 66 "parser_cocci_menhir.mly"
(Parse_aux.typed_info)
-# 23298 "parser_cocci_menhir.ml"
+# 23378 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
( let (nm,constraints,pure,ty,clt) = _1 in
Ast0.wrap
(Ast0.MetaExpr(P.clt2mcode nm clt,constraints,ty,Ast.LocalID,pure)) )
-# 23307 "parser_cocci_menhir.ml"
+# 23387 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 23338 "parser_cocci_menhir.ml"
+# 23418 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 23344 "parser_cocci_menhir.ml"
+# 23424 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
# 1301 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Paren(P.clt2mcode "(" _1,_2,
P.clt2mcode ")" _3)) )
-# 23352 "parser_cocci_menhir.ml"
+# 23432 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 23383 "parser_cocci_menhir.ml"
+# 23463 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_midzero_list_expr_eexpr_ = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 23389 "parser_cocci_menhir.ml"
+# 23469 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
Ast0.wrap(Ast0.DisjExpr(P.clt2mcode "(" _1,
code, mids,
P.clt2mcode ")" _3)) )
-# 23399 "parser_cocci_menhir.ml"
+# 23479 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_primary_expr_expr_invalid_ =
# 1308 "parser_cocci_menhir.mly"
( _1 )
-# 23423 "parser_cocci_menhir.ml"
+# 23503 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure =
# 189 "parser_cocci_menhir.mly"
( Ast0.Pure )
-# 23445 "parser_cocci_menhir.ml"
+# 23525 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure =
# 190 "parser_cocci_menhir.mly"
( Ast0.Context )
-# 23467 "parser_cocci_menhir.ml"
+# 23547 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure =
# 191 "parser_cocci_menhir.mly"
( Ast0.PureContext )
-# 23493 "parser_cocci_menhir.ml"
+# 23573 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure =
# 192 "parser_cocci_menhir.mly"
( Ast0.PureContext )
-# 23519 "parser_cocci_menhir.ml"
+# 23599 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure =
# 193 "parser_cocci_menhir.mly"
( Ast0.Impure )
-# 23536 "parser_cocci_menhir.ml"
+# 23616 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 59 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 23557 "parser_cocci_menhir.ml"
+# 23637 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_pure_ident =
# 1322 "parser_cocci_menhir.mly"
( _1 )
-# 23564 "parser_cocci_menhir.ml"
+# 23644 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident =
# 1328 "parser_cocci_menhir.mly"
( (None,P.id2name _1) )
-# 23588 "parser_cocci_menhir.ml"
+# 23668 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident =
# 1329 "parser_cocci_menhir.mly"
( _1 )
-# 23612 "parser_cocci_menhir.ml"
+# 23692 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident =
# 1330 "parser_cocci_menhir.mly"
( (None,"list") )
-# 23634 "parser_cocci_menhir.ml"
+# 23714 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident =
# 1331 "parser_cocci_menhir.mly"
( (None,"error") )
-# 23656 "parser_cocci_menhir.ml"
+# 23736 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident =
# 1332 "parser_cocci_menhir.mly"
( (None,"type") )
-# 23678 "parser_cocci_menhir.ml"
+# 23758 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident_with_not_eq_not_ceq_ =
# 1335 "parser_cocci_menhir.mly"
( (i,l) )
-# 23708 "parser_cocci_menhir.ml"
+# 23788 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident_with_not_eq_not_eq_ =
# 1335 "parser_cocci_menhir.mly"
( (i,l) )
-# 23738 "parser_cocci_menhir.ml"
+# 23818 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident_with_not_eq_not_eqe_ =
# 1335 "parser_cocci_menhir.mly"
( (i,l) )
-# 23768 "parser_cocci_menhir.ml"
+# 23848 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_pure_ident_or_meta_ident_with_not_eq_not_pos_ =
# 1335 "parser_cocci_menhir.mly"
( (i,l) )
-# 23798 "parser_cocci_menhir.ml"
+# 23878 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 130 "parser_cocci_menhir.mly"
(unit)
-# 23815 "parser_cocci_menhir.ml"
+# 23895 "parser_cocci_menhir.ml"
) =
# 171 "parser_cocci_menhir.mly"
( )
-# 23819 "parser_cocci_menhir.ml"
+# 23899 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_rule_elem_statement =
# 849 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),_1)) )
-# 23843 "parser_cocci_menhir.ml"
+# 23923 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 23869 "parser_cocci_menhir.ml"
+# 23949 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_expr = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_rule_elem_statement =
# 850 "parser_cocci_menhir.mly"
( P.exp_stm _1 _2 )
-# 23877 "parser_cocci_menhir.ml"
+# 23957 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 23908 "parser_cocci_menhir.ml"
+# 23988 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 23914 "parser_cocci_menhir.ml"
+# 23994 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_rule_elem_statement =
# 851 "parser_cocci_menhir.mly"
( P.ret_exp _1 _2 _3 )
-# 23921 "parser_cocci_menhir.ml"
+# 24001 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 23947 "parser_cocci_menhir.ml"
+# 24027 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 23952 "parser_cocci_menhir.ml"
+# 24032 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_rule_elem_statement =
# 852 "parser_cocci_menhir.mly"
( P.ret _1 _2 )
-# 23959 "parser_cocci_menhir.ml"
+# 24039 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 23985 "parser_cocci_menhir.ml"
+# 24065 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 23990 "parser_cocci_menhir.ml"
+# 24070 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_rule_elem_statement =
# 853 "parser_cocci_menhir.mly"
( P.break _1 _2 )
-# 23997 "parser_cocci_menhir.ml"
+# 24077 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 24023 "parser_cocci_menhir.ml"
+# 24103 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 24028 "parser_cocci_menhir.ml"
+# 24108 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_rule_elem_statement =
# 854 "parser_cocci_menhir.mly"
( P.cont _1 _2 )
-# 24035 "parser_cocci_menhir.ml"
+# 24115 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 24066 "parser_cocci_menhir.ml"
+# 24146 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_midzero_list_rule_elem_statement_rule_elem_statement_ = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 24072 "parser_cocci_menhir.ml"
+# 24152 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
(Ast0.Disj(P.clt2mcode "(" _1,
List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
mids, P.clt2mcode ")" _3)) )
-# 24083 "parser_cocci_menhir.ml"
+# 24163 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 152 "parser_cocci_menhir.mly"
(Ast_cocci.rulename)
-# 24139 "parser_cocci_menhir.ml"
+# 24219 "parser_cocci_menhir.ml"
) = let nm =
# 39 "standard.mly"
( None )
-# 24144 "parser_cocci_menhir.ml"
+# 24224 "parser_cocci_menhir.ml"
in
# 201 "parser_cocci_menhir.mly"
( P.make_cocci_rule_name_result nm d i a e ee )
-# 24150 "parser_cocci_menhir.ml"
+# 24230 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : (
# 152 "parser_cocci_menhir.mly"
(Ast_cocci.rulename)
-# 24212 "parser_cocci_menhir.ml"
+# 24292 "parser_cocci_menhir.ml"
) = let nm =
let x = x0 in
# 41 "standard.mly"
( Some x )
-# 24218 "parser_cocci_menhir.ml"
+# 24298 "parser_cocci_menhir.ml"
in
# 201 "parser_cocci_menhir.mly"
( P.make_cocci_rule_name_result nm d i a e ee )
-# 24224 "parser_cocci_menhir.ml"
+# 24304 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
MenhirLib.EngineTypes.endp = _endpos__2_;
MenhirLib.EngineTypes.next = {
MenhirLib.EngineTypes.state = _menhir_s;
- MenhirLib.EngineTypes.semv = scr;
- MenhirLib.EngineTypes.startp = _startpos_scr_;
- MenhirLib.EngineTypes.endp = _endpos_scr_;
+ MenhirLib.EngineTypes.startp = _startpos__1_;
+ MenhirLib.EngineTypes.endp = _endpos__1_;
MenhirLib.EngineTypes.next = _menhir_stack;
};
};
} = _menhir_stack in
let d : 'tv_depends = Obj.magic d in
let lang : 'tv_pure_ident = Obj.magic lang in
- let scr : 'tv_pure_ident = Obj.magic scr in
- let _startpos = _startpos_scr_ in
+ let _startpos = _startpos__1_ in
let _endpos = _endpos__5_ in
let _v : (
# 152 "parser_cocci_menhir.mly"
(Ast_cocci.rulename)
-# 24268 "parser_cocci_menhir.ml"
+# 24346 "parser_cocci_menhir.ml"
) =
# 203 "parser_cocci_menhir.mly"
- ( P.make_script_rule_name_result scr lang d )
-# 24272 "parser_cocci_menhir.ml"
+ ( P.make_script_rule_name_result lang d )
+# 24350 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 47 "parser_cocci_menhir.mly"
(string)
-# 24316 "parser_cocci_menhir.ml"
+# 24394 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let py : 'tv_pure_ident = Obj.magic py in
let _startpos = _startpos_py_ in
let _v : (
# 158 "parser_cocci_menhir.mly"
(string * (string * string))
-# 24324 "parser_cocci_menhir.ml"
+# 24402 "parser_cocci_menhir.ml"
) =
-# 1765 "parser_cocci_menhir.mly"
+# 1769 "parser_cocci_menhir.mly"
( (P.id2name py, (_3, P.id2name cocci)) )
-# 24328 "parser_cocci_menhir.ml"
+# 24406 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let x : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 24349 "parser_cocci_menhir.ml"
+# 24427 "parser_cocci_menhir.ml"
) = Obj.magic x in
let _startpos = _startpos_x_ in
let _endpos = _endpos_x_ in
let _v : 'tv_separated_nonempty_list_TComma_TString_ =
# 144 "standard.mly"
( [ x ] )
-# 24356 "parser_cocci_menhir.ml"
+# 24434 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let x : (
# 86 "parser_cocci_menhir.mly"
(string * Data.clt)
-# 24387 "parser_cocci_menhir.ml"
+# 24465 "parser_cocci_menhir.ml"
) = Obj.magic x in
let _startpos = _startpos_x_ in
let _endpos = _endpos_xs_ in
let _v : 'tv_separated_nonempty_list_TComma_TString_ =
# 146 "standard.mly"
( x :: xs )
-# 24394 "parser_cocci_menhir.ml"
+# 24472 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_any_strict_ =
# 144 "standard.mly"
( [ x ] )
-# 24418 "parser_cocci_menhir.ml"
+# 24496 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_any_strict_ =
# 146 "standard.mly"
( x :: xs )
-# 24452 "parser_cocci_menhir.ml"
+# 24530 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_ctype_ =
# 144 "standard.mly"
( [ x ] )
-# 24476 "parser_cocci_menhir.ml"
+# 24554 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_ctype_ =
# 146 "standard.mly"
( x :: xs )
-# 24510 "parser_cocci_menhir.ml"
+# 24588 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_d_ident_ =
# 144 "standard.mly"
( [ x ] )
-# 24534 "parser_cocci_menhir.ml"
+# 24612 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_d_ident_ =
# 146 "standard.mly"
( x :: xs )
-# 24568 "parser_cocci_menhir.ml"
+# 24646 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_dexpr_ =
# 144 "standard.mly"
( [ x ] )
-# 24592 "parser_cocci_menhir.ml"
+# 24670 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_dexpr_ =
# 146 "standard.mly"
( x :: xs )
-# 24626 "parser_cocci_menhir.ml"
+# 24704 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_ident_or_const_ =
# 144 "standard.mly"
( [ x ] )
-# 24650 "parser_cocci_menhir.ml"
+# 24728 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_ident_or_const_ =
# 146 "standard.mly"
( x :: xs )
-# 24684 "parser_cocci_menhir.ml"
+# 24762 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_meta_ident_ =
# 144 "standard.mly"
( [ x ] )
-# 24708 "parser_cocci_menhir.ml"
+# 24786 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_meta_ident_ =
# 146 "standard.mly"
( x :: xs )
-# 24742 "parser_cocci_menhir.ml"
+# 24820 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_ =
# 144 "standard.mly"
( [ x ] )
-# 24766 "parser_cocci_menhir.ml"
+# 24844 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_ =
# 146 "standard.mly"
( x :: xs )
-# 24800 "parser_cocci_menhir.ml"
+# 24878 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_ =
# 144 "standard.mly"
( [ x ] )
-# 24824 "parser_cocci_menhir.ml"
+# 24902 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_ =
# 146 "standard.mly"
( x :: xs )
-# 24858 "parser_cocci_menhir.ml"
+# 24936 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_ceq__ =
# 144 "standard.mly"
( [ x ] )
-# 24882 "parser_cocci_menhir.ml"
+# 24960 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_ceq__ =
# 146 "standard.mly"
( x :: xs )
-# 24916 "parser_cocci_menhir.ml"
+# 24994 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_eq__ =
# 144 "standard.mly"
( [ x ] )
-# 24940 "parser_cocci_menhir.ml"
+# 25018 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_eq__ =
# 146 "standard.mly"
( x :: xs )
-# 24974 "parser_cocci_menhir.ml"
+# 25052 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_eqe__ =
# 144 "standard.mly"
( [ x ] )
-# 24998 "parser_cocci_menhir.ml"
+# 25076 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_eqe__ =
# 146 "standard.mly"
( x :: xs )
-# 25032 "parser_cocci_menhir.ml"
+# 25110 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_pos__ =
# 144 "standard.mly"
( [ x ] )
-# 25056 "parser_cocci_menhir.ml"
+# 25134 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_separated_nonempty_list_TComma_pure_ident_or_meta_ident_with_not_eq_not_pos__ =
# 146 "standard.mly"
( x :: xs )
-# 25090 "parser_cocci_menhir.ml"
+# 25168 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_single_statement =
# 864 "parser_cocci_menhir.mly"
( _1 )
-# 25114 "parser_cocci_menhir.ml"
+# 25192 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25145 "parser_cocci_menhir.ml"
+# 25223 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_midzero_list_statement_statement_ = Obj.magic _2 in
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25151 "parser_cocci_menhir.ml"
+# 25229 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
(Ast0.Disj(P.clt2mcode "(" _1,
List.map (function x -> Ast0.wrap(Ast0.DOTS([x]))) code,
mids, P.clt2mcode ")" _3)) )
-# 25162 "parser_cocci_menhir.ml"
+# 25240 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_statement =
# 803 "parser_cocci_menhir.mly"
( _1 )
-# 25186 "parser_cocci_menhir.ml"
+# 25264 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 25207 "parser_cocci_menhir.ml"
+# 25285 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_statement =
# 805 "parser_cocci_menhir.mly"
( P.meta_stm _1 )
-# 25214 "parser_cocci_menhir.ml"
+# 25292 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25240 "parser_cocci_menhir.ml"
+# 25318 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_expr = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_statement =
# 807 "parser_cocci_menhir.mly"
( P.exp_stm _1 _2 )
-# 25248 "parser_cocci_menhir.ml"
+# 25326 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25290 "parser_cocci_menhir.ml"
+# 25368 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25296 "parser_cocci_menhir.ml"
+# 25374 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25301 "parser_cocci_menhir.ml"
+# 25379 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__5_ in
let _v : 'tv_statement =
# 809 "parser_cocci_menhir.mly"
( P.ifthen _1 _2 _3 _4 _5 )
-# 25308 "parser_cocci_menhir.ml"
+# 25386 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _6 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25360 "parser_cocci_menhir.ml"
+# 25438 "parser_cocci_menhir.ml"
) = Obj.magic _6 in
let _5 : 'tv_single_statement = Obj.magic _5 in
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25366 "parser_cocci_menhir.ml"
+# 25444 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25372 "parser_cocci_menhir.ml"
+# 25450 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25377 "parser_cocci_menhir.ml"
+# 25455 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__7_ in
let _v : 'tv_statement =
# 811 "parser_cocci_menhir.mly"
( P.ifthenelse _1 _2 _3 _4 _5 _6 _7 )
-# 25384 "parser_cocci_menhir.ml"
+# 25462 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _8 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25446 "parser_cocci_menhir.ml"
+# 25524 "parser_cocci_menhir.ml"
) = Obj.magic _8 in
let _7 : 'tv_option_eexpr_ = Obj.magic _7 in
let _6 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25452 "parser_cocci_menhir.ml"
+# 25530 "parser_cocci_menhir.ml"
) = Obj.magic _6 in
let _5 : 'tv_option_eexpr_ = Obj.magic _5 in
let _4 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25458 "parser_cocci_menhir.ml"
+# 25536 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_option_eexpr_ = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25464 "parser_cocci_menhir.ml"
+# 25542 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25469 "parser_cocci_menhir.ml"
+# 25547 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__9_ in
let _v : 'tv_statement =
# 814 "parser_cocci_menhir.mly"
( P.forloop _1 _2 _3 _4 _5 _6 _7 _8 _9 )
-# 25476 "parser_cocci_menhir.ml"
+# 25554 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25518 "parser_cocci_menhir.ml"
+# 25596 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25524 "parser_cocci_menhir.ml"
+# 25602 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25529 "parser_cocci_menhir.ml"
+# 25607 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__5_ in
let _v : 'tv_statement =
# 816 "parser_cocci_menhir.mly"
( P.whileloop _1 _2 _3 _4 _5 )
-# 25536 "parser_cocci_menhir.ml"
+# 25614 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _7 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25587 "parser_cocci_menhir.ml"
+# 25665 "parser_cocci_menhir.ml"
) = Obj.magic _7 in
let _6 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25592 "parser_cocci_menhir.ml"
+# 25670 "parser_cocci_menhir.ml"
) = Obj.magic _6 in
let _5 : 'tv_eexpr = Obj.magic _5 in
let _4 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25598 "parser_cocci_menhir.ml"
+# 25676 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25603 "parser_cocci_menhir.ml"
+# 25681 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_single_statement = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25609 "parser_cocci_menhir.ml"
+# 25687 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__7_ in
let _v : 'tv_statement =
# 818 "parser_cocci_menhir.mly"
( P.doloop _1 _2 _3 _4 _5 _6 _7 )
-# 25616 "parser_cocci_menhir.ml"
+# 25694 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25658 "parser_cocci_menhir.ml"
+# 25736 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr_list_option = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25664 "parser_cocci_menhir.ml"
+# 25742 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_iter_ident = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_statement =
# 820 "parser_cocci_menhir.mly"
( P.iterator _1 _2 _3 _4 _5 )
-# 25672 "parser_cocci_menhir.ml"
+# 25750 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _7 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 25723 "parser_cocci_menhir.ml"
+# 25801 "parser_cocci_menhir.ml"
) = Obj.magic _7 in
let _6 : 'tv_list_case_line_ = Obj.magic _6 in
let _5 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 25729 "parser_cocci_menhir.ml"
+# 25807 "parser_cocci_menhir.ml"
) = Obj.magic _5 in
let _4 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 25734 "parser_cocci_menhir.ml"
+# 25812 "parser_cocci_menhir.ml"
) = Obj.magic _4 in
let _3 : 'tv_eexpr = Obj.magic _3 in
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25740 "parser_cocci_menhir.ml"
+# 25818 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25745 "parser_cocci_menhir.ml"
+# 25823 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__7_ in
let _v : 'tv_statement =
# 822 "parser_cocci_menhir.mly"
( P.switch _1 _2 _3 _4 _5 _6 _7 )
-# 25752 "parser_cocci_menhir.ml"
+# 25830 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25783 "parser_cocci_menhir.ml"
+# 25861 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_eexpr = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25789 "parser_cocci_menhir.ml"
+# 25867 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_statement =
# 823 "parser_cocci_menhir.mly"
( P.ret_exp _1 _2 _3 )
-# 25796 "parser_cocci_menhir.ml"
+# 25874 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25822 "parser_cocci_menhir.ml"
+# 25900 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 57 "parser_cocci_menhir.mly"
(Data.clt)
-# 25827 "parser_cocci_menhir.ml"
+# 25905 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_statement =
# 824 "parser_cocci_menhir.mly"
( P.ret _1 _2 )
-# 25834 "parser_cocci_menhir.ml"
+# 25912 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25860 "parser_cocci_menhir.ml"
+# 25938 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 25865 "parser_cocci_menhir.ml"
+# 25943 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_statement =
# 825 "parser_cocci_menhir.mly"
( P.break _1 _2 )
-# 25872 "parser_cocci_menhir.ml"
+# 25950 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25898 "parser_cocci_menhir.ml"
+# 25976 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 25903 "parser_cocci_menhir.ml"
+# 25981 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_statement =
# 826 "parser_cocci_menhir.mly"
( P.cont _1 _2 )
-# 25910 "parser_cocci_menhir.ml"
+# 25988 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 25936 "parser_cocci_menhir.ml"
+# 26014 "parser_cocci_menhir.ml"
) = Obj.magic _2 in
let _1 : 'tv_ident = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _v : 'tv_statement =
# 827 "parser_cocci_menhir.mly"
( P.label _1 _2 )
-# 25944 "parser_cocci_menhir.ml"
+# 26022 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 25975 "parser_cocci_menhir.ml"
+# 26053 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_ident = Obj.magic _2 in
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 25981 "parser_cocci_menhir.ml"
+# 26059 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_statement =
# 828 "parser_cocci_menhir.mly"
( P.goto _1 _2 _3 )
-# 25988 "parser_cocci_menhir.ml"
+# 26066 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _3 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 26019 "parser_cocci_menhir.ml"
+# 26097 "parser_cocci_menhir.ml"
) = Obj.magic _3 in
let _2 : 'tv_fun_start = Obj.magic _2 in
let _1 : (
# 100 "parser_cocci_menhir.mly"
(Data.clt)
-# 26025 "parser_cocci_menhir.ml"
+# 26103 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_statement =
# 830 "parser_cocci_menhir.mly"
( P.seq _1 _2 _3 )
-# 26032 "parser_cocci_menhir.ml"
+# 26110 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 26059 "parser_cocci_menhir.ml"
+# 26137 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos_w_ in
let _v : 'tv_stm_dots =
# 834 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Dots(P.clt2mcode "..." _1, List.concat w)) )
-# 26066 "parser_cocci_menhir.ml"
+# 26144 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let c : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 26102 "parser_cocci_menhir.ml"
+# 26180 "parser_cocci_menhir.ml"
) = Obj.magic c in
let b : 'tv_nest_start = Obj.magic b in
let w : 'tv_list_whenppdecs_ = Obj.magic w in
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 26109 "parser_cocci_menhir.ml"
+# 26187 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos_c_ in
# 836 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Nest(P.clt2mcode "<..." _1, b,
P.clt2mcode "...>" c, List.concat w, false)) )
-# 26117 "parser_cocci_menhir.ml"
+# 26195 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let c : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 26153 "parser_cocci_menhir.ml"
+# 26231 "parser_cocci_menhir.ml"
) = Obj.magic c in
let b : 'tv_nest_start = Obj.magic b in
let w : 'tv_list_whenppdecs_ = Obj.magic w in
let _1 : (
# 72 "parser_cocci_menhir.mly"
(Data.clt)
-# 26160 "parser_cocci_menhir.ml"
+# 26238 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos_c_ in
# 839 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Nest(P.clt2mcode "<+..." _1, b,
P.clt2mcode "...+>" c, List.concat w, true)) )
-# 26168 "parser_cocci_menhir.ml"
+# 26246 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let s : (
# 53 "parser_cocci_menhir.mly"
(Data.clt)
-# 26189 "parser_cocci_menhir.ml"
+# 26267 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_s_ in
let _v : 'tv_storage =
# 762 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Static s )
-# 26196 "parser_cocci_menhir.ml"
+# 26274 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let s : (
# 53 "parser_cocci_menhir.mly"
(Data.clt)
-# 26217 "parser_cocci_menhir.ml"
+# 26295 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_s_ in
let _v : 'tv_storage =
# 763 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Auto s )
-# 26224 "parser_cocci_menhir.ml"
+# 26302 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let s : (
# 53 "parser_cocci_menhir.mly"
(Data.clt)
-# 26245 "parser_cocci_menhir.ml"
+# 26323 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_s_ in
let _v : 'tv_storage =
# 764 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Register s )
-# 26252 "parser_cocci_menhir.ml"
+# 26330 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let s : (
# 53 "parser_cocci_menhir.mly"
(Data.clt)
-# 26273 "parser_cocci_menhir.ml"
+# 26351 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_s_ in
let _v : 'tv_storage =
# 765 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Extern s )
-# 26280 "parser_cocci_menhir.ml"
+# 26358 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_struct_decl =
# 488 "parser_cocci_menhir.mly"
( [] )
-# 26302 "parser_cocci_menhir.ml"
+# 26380 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 26333 "parser_cocci_menhir.ml"
+# 26411 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let t : 'tv_ctype = Obj.magic t in
# 490 "parser_cocci_menhir.mly"
( let (id,fn) = d in
[Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] )
-# 26343 "parser_cocci_menhir.ml"
+# 26421 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 26404 "parser_cocci_menhir.ml"
+# 26482 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let rp2 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 26409 "parser_cocci_menhir.ml"
+# 26487 "parser_cocci_menhir.ml"
) = Obj.magic rp2 in
let p : 'tv_decl_list_name_opt_decl_ = Obj.magic p in
let lp2 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 26415 "parser_cocci_menhir.ml"
+# 26493 "parser_cocci_menhir.ml"
) = Obj.magic lp2 in
let rp1 : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 26420 "parser_cocci_menhir.ml"
+# 26498 "parser_cocci_menhir.ml"
) = Obj.magic rp1 in
let d : 'tv_d_ident = Obj.magic d in
let st : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 26426 "parser_cocci_menhir.ml"
+# 26504 "parser_cocci_menhir.ml"
) = Obj.magic st in
let lp1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 26431 "parser_cocci_menhir.ml"
+# 26509 "parser_cocci_menhir.ml"
) = Obj.magic lp1 in
let t : 'tv_fn_ctype = Obj.magic t in
let _startpos = _startpos_t_ in
(t,P.clt2mcode "(" lp1,P.clt2mcode "*" st,P.clt2mcode ")" rp1,
P.clt2mcode "(" lp2,p,P.clt2mcode ")" rp2)) in
[Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv))] )
-# 26445 "parser_cocci_menhir.ml"
+# 26523 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 26476 "parser_cocci_menhir.ml"
+# 26554 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 39 "standard.mly"
( None )
-# 26486 "parser_cocci_menhir.ml"
+# 26564 "parser_cocci_menhir.ml"
in
( let (id,fn) = d in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
[Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] )
-# 26494 "parser_cocci_menhir.ml"
+# 26572 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let pv : (
# 106 "parser_cocci_menhir.mly"
(Data.clt)
-# 26530 "parser_cocci_menhir.ml"
+# 26608 "parser_cocci_menhir.ml"
) = Obj.magic pv in
let d : 'tv_d_ident = Obj.magic d in
let i : 'tv_pure_ident = Obj.magic i in
# 41 "standard.mly"
( Some x )
-# 26542 "parser_cocci_menhir.ml"
+# 26620 "parser_cocci_menhir.ml"
in
( let (id,fn) = d in
let idtype = P.make_cv cv (Ast0.wrap (Ast0.TypeName(P.id2mcode i))) in
[Ast0.wrap(Ast0.UnInit(None,fn idtype,id,P.clt2mcode ";" pv))] )
-# 26550 "parser_cocci_menhir.ml"
+# 26628 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_struct_decl_list =
# 507 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS(_1)) )
-# 26574 "parser_cocci_menhir.ml"
+# 26652 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_struct_decl_list_start =
# 510 "parser_cocci_menhir.mly"
( _1 )
-# 26598 "parser_cocci_menhir.ml"
+# 26676 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_struct_decl_list_start =
# 511 "parser_cocci_menhir.mly"
( _1@_2 )
-# 26628 "parser_cocci_menhir.ml"
+# 26706 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_struct_decl_list_start =
# 513 "parser_cocci_menhir.mly"
( (P.mkddots "..." d)::r )
-# 26658 "parser_cocci_menhir.ml"
+# 26736 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let s : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 26679 "parser_cocci_menhir.ml"
+# 26757 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_s_ in
let _v : 'tv_struct_or_union =
# 484 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Struct s )
-# 26686 "parser_cocci_menhir.ml"
+# 26764 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let u : (
# 50 "parser_cocci_menhir.mly"
(Data.clt)
-# 26707 "parser_cocci_menhir.ml"
+# 26785 "parser_cocci_menhir.ml"
) = Obj.magic u in
let _startpos = _startpos_u_ in
let _endpos = _endpos_u_ in
let _v : 'tv_struct_or_union =
# 485 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Union u )
-# 26714 "parser_cocci_menhir.ml"
+# 26792 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_top_eexpr =
# 1137 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp(_1)))) )
-# 26738 "parser_cocci_menhir.ml"
+# 26816 "parser_cocci_menhir.ml"
+ in
+ _menhir_env.MenhirLib.EngineTypes.stack <- {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = Obj.repr _v;
+ MenhirLib.EngineTypes.startp = _startpos;
+ MenhirLib.EngineTypes.endp = _endpos;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ });
+ (fun _menhir_env ->
+ let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+ let {
+ MenhirLib.EngineTypes.semv = _3;
+ MenhirLib.EngineTypes.startp = _startpos__3_;
+ MenhirLib.EngineTypes.endp = _endpos__3_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.semv = _2;
+ MenhirLib.EngineTypes.startp = _startpos__2_;
+ MenhirLib.EngineTypes.endp = _endpos__2_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = _1;
+ MenhirLib.EngineTypes.startp = _startpos__1_;
+ MenhirLib.EngineTypes.endp = _endpos__1_;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ };
+ };
+ } = _menhir_stack in
+ let _3 : (
+# 100 "parser_cocci_menhir.mly"
+ (Data.clt)
+# 26847 "parser_cocci_menhir.ml"
+ ) = Obj.magic _3 in
+ let _2 : 'tv_initialize_list = Obj.magic _2 in
+ let _1 : (
+# 100 "parser_cocci_menhir.mly"
+ (Data.clt)
+# 26853 "parser_cocci_menhir.ml"
+ ) = Obj.magic _1 in
+ let _startpos = _startpos__1_ in
+ let _endpos = _endpos__3_ in
+ let _v : 'tv_top_init =
+# 1547 "parser_cocci_menhir.mly"
+ ( Ast0.wrap(Ast0.InitList(P.clt2mcode "{" _1,_2,P.clt2mcode "}" _3)) )
+# 26860 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_toplevel_after_dots =
-# 1534 "parser_cocci_menhir.mly"
+# 1535 "parser_cocci_menhir.mly"
([])
-# 26755 "parser_cocci_menhir.ml"
+# 26877 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_dots =
-# 1535 "parser_cocci_menhir.mly"
+# 1536 "parser_cocci_menhir.mly"
(_2)
-# 26783 "parser_cocci_menhir.ml"
+# 26905 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_dots =
-# 1536 "parser_cocci_menhir.mly"
+# 1537 "parser_cocci_menhir.mly"
((Ast0.wrap(Ast0.Exp(_1)))::_2)
-# 26813 "parser_cocci_menhir.ml"
+# 26935 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_dots =
-# 1537 "parser_cocci_menhir.mly"
+# 1538 "parser_cocci_menhir.mly"
(_1@_2)
-# 26843 "parser_cocci_menhir.ml"
+# 26965 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_dots_init =
-# 1525 "parser_cocci_menhir.mly"
+# 1526 "parser_cocci_menhir.mly"
(_2)
-# 26871 "parser_cocci_menhir.ml"
+# 26993 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_dots_init =
-# 1526 "parser_cocci_menhir.mly"
+# 1527 "parser_cocci_menhir.mly"
((Ast0.wrap(Ast0.Exp(_1)))::_2)
-# 26901 "parser_cocci_menhir.ml"
+# 27023 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_dots_init =
-# 1527 "parser_cocci_menhir.mly"
+# 1528 "parser_cocci_menhir.mly"
(_1@_2)
-# 26931 "parser_cocci_menhir.ml"
+# 27053 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_toplevel_after_exp =
-# 1530 "parser_cocci_menhir.mly"
+# 1531 "parser_cocci_menhir.mly"
([])
-# 26948 "parser_cocci_menhir.ml"
+# 27070 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_exp =
-# 1531 "parser_cocci_menhir.mly"
+# 1532 "parser_cocci_menhir.mly"
(_1::_2)
-# 26978 "parser_cocci_menhir.ml"
+# 27100 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _menhir_env.MenhirLib.EngineTypes.lexbuf.Lexing.lex_start_p in
let _endpos = _startpos in
let _v : 'tv_toplevel_after_stm =
-# 1540 "parser_cocci_menhir.mly"
+# 1541 "parser_cocci_menhir.mly"
([])
-# 26995 "parser_cocci_menhir.ml"
+# 27117 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_stm =
-# 1541 "parser_cocci_menhir.mly"
+# 1542 "parser_cocci_menhir.mly"
(_1::_2)
-# 27025 "parser_cocci_menhir.ml"
+# 27147 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_after_stm =
-# 1542 "parser_cocci_menhir.mly"
+# 1543 "parser_cocci_menhir.mly"
(_1@_2)
-# 27055 "parser_cocci_menhir.ml"
+# 27177 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_seq_start_toplevel_after_dots_ =
-# 1520 "parser_cocci_menhir.mly"
+# 1521 "parser_cocci_menhir.mly"
( _1::_2 )
-# 27085 "parser_cocci_menhir.ml"
+# 27207 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_seq_start_toplevel_after_dots_ =
-# 1521 "parser_cocci_menhir.mly"
+# 1522 "parser_cocci_menhir.mly"
( (Ast0.wrap(Ast0.Exp(_1)))::_2 )
-# 27115 "parser_cocci_menhir.ml"
+# 27237 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_seq_start_toplevel_after_dots_ =
-# 1522 "parser_cocci_menhir.mly"
+# 1523 "parser_cocci_menhir.mly"
( _1@_2 )
-# 27145 "parser_cocci_menhir.ml"
+# 27267 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_seq_start_toplevel_after_dots_init_ =
-# 1520 "parser_cocci_menhir.mly"
+# 1521 "parser_cocci_menhir.mly"
( _1::_2 )
-# 27175 "parser_cocci_menhir.ml"
+# 27297 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_seq_start_toplevel_after_dots_init_ =
-# 1521 "parser_cocci_menhir.mly"
+# 1522 "parser_cocci_menhir.mly"
( (Ast0.wrap(Ast0.Exp(_1)))::_2 )
-# 27205 "parser_cocci_menhir.ml"
+# 27327 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_toplevel_seq_start_toplevel_after_dots_init_ =
-# 1522 "parser_cocci_menhir.mly"
+# 1523 "parser_cocci_menhir.mly"
( _1@_2 )
-# 27235 "parser_cocci_menhir.ml"
+# 27357 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_typedef_ident =
# 1434 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.TypeName(P.id2mcode _1)) )
-# 27259 "parser_cocci_menhir.ml"
+# 27381 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 64 "parser_cocci_menhir.mly"
(Parse_aux.info)
-# 27280 "parser_cocci_menhir.ml"
+# 27402 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
# 1436 "parser_cocci_menhir.mly"
( let (nm,pure,clt) = _1 in
Ast0.wrap(Ast0.MetaType(P.clt2mcode nm clt,pure)) )
-# 27288 "parser_cocci_menhir.ml"
+# 27410 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_eexpr_dot_expressions_ =
# 1225 "parser_cocci_menhir.mly"
( _1 )
-# 27312 "parser_cocci_menhir.ml"
+# 27434 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 27339 "parser_cocci_menhir.ml"
+# 27461 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_dot_expressions_ =
# 1227 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Inc _1)) )
-# 27346 "parser_cocci_menhir.ml"
+# 27468 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 27373 "parser_cocci_menhir.ml"
+# 27495 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_dot_expressions_ =
# 1229 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Dec _1)) )
-# 27380 "parser_cocci_menhir.ml"
+# 27502 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_eexpr_dot_expressions_ =
# 1231 "parser_cocci_menhir.mly"
( let mcode = _1 in Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 27410 "parser_cocci_menhir.ml"
+# 27532 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 27437 "parser_cocci_menhir.ml"
+# 27559 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1233 "parser_cocci_menhir.mly"
( let mcode = P.clt2mcode Ast.Not _1 in
Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 27445 "parser_cocci_menhir.ml"
+# 27567 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 27472 "parser_cocci_menhir.ml"
+# 27594 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_dot_expressions_ =
# 1236 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" _1, _2)) )
-# 27479 "parser_cocci_menhir.ml"
+# 27601 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 27515 "parser_cocci_menhir.ml"
+# 27637 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 27521 "parser_cocci_menhir.ml"
+# 27643 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let s : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 27526 "parser_cocci_menhir.ml"
+# 27648 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_rp_ in
( Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
P.clt2mcode "(" lp,t,
P.clt2mcode ")" rp)) )
-# 27535 "parser_cocci_menhir.ml"
+# 27657 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_eexpr_invalid_ =
# 1225 "parser_cocci_menhir.mly"
( _1 )
-# 27559 "parser_cocci_menhir.ml"
+# 27681 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 27586 "parser_cocci_menhir.ml"
+# 27708 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_invalid_ =
# 1227 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Inc _1)) )
-# 27593 "parser_cocci_menhir.ml"
+# 27715 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 27620 "parser_cocci_menhir.ml"
+# 27742 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_invalid_ =
# 1229 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Dec _1)) )
-# 27627 "parser_cocci_menhir.ml"
+# 27749 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_eexpr_invalid_ =
# 1231 "parser_cocci_menhir.mly"
( let mcode = _1 in Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 27657 "parser_cocci_menhir.ml"
+# 27779 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 27684 "parser_cocci_menhir.ml"
+# 27806 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1233 "parser_cocci_menhir.mly"
( let mcode = P.clt2mcode Ast.Not _1 in
Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 27692 "parser_cocci_menhir.ml"
+# 27814 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 27719 "parser_cocci_menhir.ml"
+# 27841 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_invalid_ =
# 1236 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" _1, _2)) )
-# 27726 "parser_cocci_menhir.ml"
+# 27848 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 27762 "parser_cocci_menhir.ml"
+# 27884 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 27768 "parser_cocci_menhir.ml"
+# 27890 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let s : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 27773 "parser_cocci_menhir.ml"
+# 27895 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_rp_ in
( Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
P.clt2mcode "(" lp,t,
P.clt2mcode ")" rp)) )
-# 27782 "parser_cocci_menhir.ml"
+# 27904 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_eexpr_nest_expressions_ =
# 1225 "parser_cocci_menhir.mly"
( _1 )
-# 27806 "parser_cocci_menhir.ml"
+# 27928 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 27833 "parser_cocci_menhir.ml"
+# 27955 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_nest_expressions_ =
# 1227 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Inc _1)) )
-# 27840 "parser_cocci_menhir.ml"
+# 27962 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 27867 "parser_cocci_menhir.ml"
+# 27989 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_nest_expressions_ =
# 1229 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Dec _1)) )
-# 27874 "parser_cocci_menhir.ml"
+# 27996 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_eexpr_nest_expressions_ =
# 1231 "parser_cocci_menhir.mly"
( let mcode = _1 in Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 27904 "parser_cocci_menhir.ml"
+# 28026 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 27931 "parser_cocci_menhir.ml"
+# 28053 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1233 "parser_cocci_menhir.mly"
( let mcode = P.clt2mcode Ast.Not _1 in
Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 27939 "parser_cocci_menhir.ml"
+# 28061 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 27966 "parser_cocci_menhir.ml"
+# 28088 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_eexpr_nest_expressions_ =
# 1236 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" _1, _2)) )
-# 27973 "parser_cocci_menhir.ml"
+# 28095 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 28009 "parser_cocci_menhir.ml"
+# 28131 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 28015 "parser_cocci_menhir.ml"
+# 28137 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let s : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 28020 "parser_cocci_menhir.ml"
+# 28142 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_rp_ in
( Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
P.clt2mcode "(" lp,t,
P.clt2mcode ")" rp)) )
-# 28029 "parser_cocci_menhir.ml"
+# 28151 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_expr_invalid_ =
# 1225 "parser_cocci_menhir.mly"
( _1 )
-# 28053 "parser_cocci_menhir.ml"
+# 28175 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 28080 "parser_cocci_menhir.ml"
+# 28202 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_expr_invalid_ =
# 1227 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Inc _1)) )
-# 28087 "parser_cocci_menhir.ml"
+# 28209 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 84 "parser_cocci_menhir.mly"
(Data.clt)
-# 28114 "parser_cocci_menhir.ml"
+# 28236 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_expr_invalid_ =
# 1229 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.Infix (_2, P.clt2mcode Ast.Dec _1)) )
-# 28121 "parser_cocci_menhir.ml"
+# 28243 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_unary_expr_expr_invalid_ =
# 1231 "parser_cocci_menhir.mly"
( let mcode = _1 in Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 28151 "parser_cocci_menhir.ml"
+# 28273 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 28178 "parser_cocci_menhir.ml"
+# 28300 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
# 1233 "parser_cocci_menhir.mly"
( let mcode = P.clt2mcode Ast.Not _1 in
Ast0.wrap(Ast0.Unary(_2, mcode)) )
-# 28186 "parser_cocci_menhir.ml"
+# 28308 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 28213 "parser_cocci_menhir.ml"
+# 28335 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_unary_expr_expr_invalid_ =
# 1236 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.SizeOfExpr (P.clt2mcode "sizeof" _1, _2)) )
-# 28220 "parser_cocci_menhir.ml"
+# 28342 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rp : (
# 76 "parser_cocci_menhir.mly"
(Data.clt)
-# 28256 "parser_cocci_menhir.ml"
+# 28378 "parser_cocci_menhir.ml"
) = Obj.magic rp in
let t : 'tv_ctype = Obj.magic t in
let lp : (
# 75 "parser_cocci_menhir.mly"
(Data.clt)
-# 28262 "parser_cocci_menhir.ml"
+# 28384 "parser_cocci_menhir.ml"
) = Obj.magic lp in
let s : (
# 58 "parser_cocci_menhir.mly"
(Data.clt)
-# 28267 "parser_cocci_menhir.ml"
+# 28389 "parser_cocci_menhir.ml"
) = Obj.magic s in
let _startpos = _startpos_s_ in
let _endpos = _endpos_rp_ in
( Ast0.wrap(Ast0.SizeOfType (P.clt2mcode "sizeof" s,
P.clt2mcode "(" lp,t,
P.clt2mcode ")" rp)) )
-# 28276 "parser_cocci_menhir.ml"
+# 28398 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 92 "parser_cocci_menhir.mly"
(Data.clt)
-# 28297 "parser_cocci_menhir.ml"
+# 28419 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_unary_op =
# 1242 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.GetRef _1 )
-# 28304 "parser_cocci_menhir.ml"
+# 28426 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 28325 "parser_cocci_menhir.ml"
+# 28447 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_unary_op =
# 1243 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.DeRef _1 )
-# 28332 "parser_cocci_menhir.ml"
+# 28454 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 28353 "parser_cocci_menhir.ml"
+# 28475 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_unary_op =
# 1244 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.UnPlus _1 )
-# 28360 "parser_cocci_menhir.ml"
+# 28482 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 97 "parser_cocci_menhir.mly"
(Data.clt)
-# 28381 "parser_cocci_menhir.ml"
+# 28503 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_unary_op =
# 1245 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.UnMinus _1 )
-# 28388 "parser_cocci_menhir.ml"
+# 28510 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _1 : (
# 98 "parser_cocci_menhir.mly"
(Data.clt)
-# 28409 "parser_cocci_menhir.ml"
+# 28531 "parser_cocci_menhir.ml"
) = Obj.magic _1 in
let _startpos = _startpos__1_ in
let _endpos = _endpos__1_ in
let _v : 'tv_unary_op =
# 1246 "parser_cocci_menhir.mly"
( P.clt2mcode Ast.Tilde _1 )
-# 28416 "parser_cocci_menhir.ml"
+# 28538 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_when_start =
-# 1634 "parser_cocci_menhir.mly"
+# 1640 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS((Ast0.wrap(Ast0.Exp(_1)))::_2)) )
-# 28446 "parser_cocci_menhir.ml"
+# 28568 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__2_ in
let _v : 'tv_when_start =
-# 1636 "parser_cocci_menhir.mly"
+# 1642 "parser_cocci_menhir.mly"
( Ast0.wrap(Ast0.DOTS(_1@_2)) )
-# 28476 "parser_cocci_menhir.ml"
+# 28598 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_whenexp =
# 1156 "parser_cocci_menhir.mly"
( w )
-# 28512 "parser_cocci_menhir.ml"
+# 28634 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _v : 'tv_whenppdecs =
# 843 "parser_cocci_menhir.mly"
( w )
-# 28536 "parser_cocci_menhir.ml"
+# 28658 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__4_ in
let _v : 'tv_whens_when_start_rule_elem_statement_ =
-# 1706 "parser_cocci_menhir.mly"
+# 1708 "parser_cocci_menhir.mly"
( [Ast0.WhenNot w] )
-# 28572 "parser_cocci_menhir.ml"
+# 28694 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__4_ in
let _v : 'tv_whens_when_start_rule_elem_statement_ =
-# 1707 "parser_cocci_menhir.mly"
+# 1709 "parser_cocci_menhir.mly"
( [Ast0.WhenAlways w] )
-# 28608 "parser_cocci_menhir.ml"
+# 28730 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let _startpos = _startpos__1_ in
let _endpos = _endpos__3_ in
let _v : 'tv_whens_when_start_rule_elem_statement_ =
-# 1709 "parser_cocci_menhir.mly"
+# 1711 "parser_cocci_menhir.mly"
( List.map (function x -> Ast0.WhenModifier(x)) _2 )
-# 28640 "parser_cocci_menhir.ml"
+# 28762 "parser_cocci_menhir.ml"
+ in
+ _menhir_env.MenhirLib.EngineTypes.stack <- {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = Obj.repr _v;
+ MenhirLib.EngineTypes.startp = _startpos;
+ MenhirLib.EngineTypes.endp = _endpos;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ });
+ (fun _menhir_env ->
+ let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+ let {
+ MenhirLib.EngineTypes.startp = _startpos__4_;
+ MenhirLib.EngineTypes.endp = _endpos__4_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.semv = e;
+ MenhirLib.EngineTypes.startp = _startpos_e_;
+ MenhirLib.EngineTypes.endp = _endpos_e_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.startp = _startpos__2_;
+ MenhirLib.EngineTypes.endp = _endpos__2_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.startp = _startpos__1_;
+ MenhirLib.EngineTypes.endp = _endpos__1_;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ };
+ };
+ };
+ } = _menhir_stack in
+ let e : 'tv_eexpr = Obj.magic e in
+ let _startpos = _startpos__1_ in
+ let _endpos = _endpos__4_ in
+ let _v : 'tv_whens_when_start_rule_elem_statement_ =
+# 1712 "parser_cocci_menhir.mly"
+ ( [Ast0.WhenNotTrue e] )
+# 28798 "parser_cocci_menhir.ml"
+ in
+ _menhir_env.MenhirLib.EngineTypes.stack <- {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.semv = Obj.repr _v;
+ MenhirLib.EngineTypes.startp = _startpos;
+ MenhirLib.EngineTypes.endp = _endpos;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ });
+ (fun _menhir_env ->
+ let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+ let {
+ MenhirLib.EngineTypes.startp = _startpos__4_;
+ MenhirLib.EngineTypes.endp = _endpos__4_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.semv = e;
+ MenhirLib.EngineTypes.startp = _startpos_e_;
+ MenhirLib.EngineTypes.endp = _endpos_e_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.startp = _startpos__2_;
+ MenhirLib.EngineTypes.endp = _endpos__2_;
+ MenhirLib.EngineTypes.next = {
+ MenhirLib.EngineTypes.state = _menhir_s;
+ MenhirLib.EngineTypes.startp = _startpos__1_;
+ MenhirLib.EngineTypes.endp = _endpos__1_;
+ MenhirLib.EngineTypes.next = _menhir_stack;
+ };
+ };
+ };
+ } = _menhir_stack in
+ let e : 'tv_eexpr = Obj.magic e in
+ let _startpos = _startpos__1_ in
+ let _endpos = _endpos__4_ in
+ let _v : 'tv_whens_when_start_rule_elem_statement_ =
+# 1713 "parser_cocci_menhir.mly"
+ ( [Ast0.WhenNotFalse e] )
+# 28834 "parser_cocci_menhir.ml"
in
_menhir_env.MenhirLib.EngineTypes.stack <- {
MenhirLib.EngineTypes.state = _menhir_s;
let rec script_meta_main =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1479 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1493 lexer lexbuf) : (
# 158 "parser_cocci_menhir.mly"
(string * (string * string))
-# 28664 "parser_cocci_menhir.ml"
+# 28858 "parser_cocci_menhir.ml"
))
and rule_name =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1424 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1437 lexer lexbuf) : (
# 152 "parser_cocci_menhir.mly"
(Ast_cocci.rulename)
-# 28672 "parser_cocci_menhir.ml"
+# 28866 "parser_cocci_menhir.ml"
))
and reinit =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1422 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1435 lexer lexbuf) : (
# 130 "parser_cocci_menhir.mly"
(unit)
-# 28680 "parser_cocci_menhir.ml"
+# 28874 "parser_cocci_menhir.ml"
))
and plus_main =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1387 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1399 lexer lexbuf) : (
# 139 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 28688 "parser_cocci_menhir.ml"
+# 28882 "parser_cocci_menhir.ml"
))
and plus_exp_main =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1378 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1390 lexer lexbuf) : (
# 142 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 28696 "parser_cocci_menhir.ml"
+# 28890 "parser_cocci_menhir.ml"
))
and never_used =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1372 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1384 lexer lexbuf) : (
# 167 "parser_cocci_menhir.mly"
(unit)
-# 28704 "parser_cocci_menhir.ml"
+# 28898 "parser_cocci_menhir.ml"
))
and minus_main =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1301 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1309 lexer lexbuf) : (
# 133 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 28712 "parser_cocci_menhir.ml"
+# 28906 "parser_cocci_menhir.ml"
))
and minus_exp_main =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1277 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1285 lexer lexbuf) : (
# 136 "parser_cocci_menhir.mly"
(Ast0_cocci.rule)
-# 28720 "parser_cocci_menhir.ml"
+# 28914 "parser_cocci_menhir.ml"
))
and meta_main =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1274 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1282 lexer lexbuf) : (
# 156 "parser_cocci_menhir.mly"
((Ast_cocci.metavar,Ast_cocci.metavar) Common.either list)
-# 28728 "parser_cocci_menhir.ml"
+# 28922 "parser_cocci_menhir.ml"
))
and iso_rule_name =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1270 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1278 lexer lexbuf) : (
# 148 "parser_cocci_menhir.mly"
(Ast_cocci.rulename)
-# 28736 "parser_cocci_menhir.ml"
+# 28930 "parser_cocci_menhir.ml"
))
and iso_meta_main =
fun lexer lexbuf ->
- (Obj.magic (MenhirInterpreter.entry 1078 lexer lexbuf) : (
+ (Obj.magic (MenhirInterpreter.entry 1086 lexer lexbuf) : (
# 164 "parser_cocci_menhir.mly"
((Ast_cocci.metavar,Ast_cocci.metavar) Common.either list)
-# 28744 "parser_cocci_menhir.ml"
+# 28938 "parser_cocci_menhir.ml"
))
and iso_main =
(Obj.magic (MenhirInterpreter.entry 10 lexer lexbuf) : (
# 161 "parser_cocci_menhir.mly"
(Ast0_cocci.anything list list)
-# 28752 "parser_cocci_menhir.ml"
+# 28946 "parser_cocci_menhir.ml"
))
and include_main =
(Obj.magic (MenhirInterpreter.entry 0 lexer lexbuf) : (
# 145 "parser_cocci_menhir.mly"
((string,string) Common.either list)
-# 28760 "parser_cocci_menhir.ml"
+# 28954 "parser_cocci_menhir.ml"
))
| TWhy0
| TWhy of (Data.clt)
| TWhile of (Data.clt)
+ | TWhenTrue of (Data.clt)
+ | TWhenFalse of (Data.clt)
| TWhen of (Data.clt)
| TUsing
| TTypedef
| TSizeof of (Data.clt)
| TShOp of (Ast_cocci.arithOp * Data.clt)
| TScriptData of (string)
+ | TScript
| TRuleName of (string)
| TRightIso
| TReverse
| TOn
| TOPar0 of (Data.clt)
| TOPar of (Data.clt)
+ | TOInit of (Data.clt)
| TOEllipsis of (Data.clt)
| TOCro of (Data.clt)
| TOBrace of (Data.clt)
%token Tlist TFresh TConstant TError TWords TWhy0 TPlus0 TBang0
%token TPure TContext
%token TTypedef TDeclarer TIterator TName TPosition TPosAny
-%token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall
+%token TUsing TDisable TExtends TDepends TOn TEver TNever TExists TForall TScript
%token TReverse TNothing
%token<string> TRuleName
%token <string> TScriptData
%token <Data.clt> TEllipsis TOEllipsis TCEllipsis TPOEllipsis TPCEllipsis
-%token <Data.clt> TWhen TAny TStrict TLineEnd
+%token <Data.clt> TWhen TWhenTrue TWhenFalse TAny TStrict TLineEnd
%token <Data.clt> TWhy TDotDot TBang TOPar TOPar0
%token <Data.clt> TMid0 TCPar TCPar0
%token <Data.clt> TPlus TMinus
%token <Data.clt> TMul TTilde
-%token <Data.clt> TOBrace TCBrace
+%token <Data.clt> TOBrace TCBrace TOInit
%token <Data.clt> TOCro TCCro
%token <Data.clt> TPtrOp
nm=ioption(pure_ident) extends d=depends i=loption(choose_iso)
a=loption(disable) e=exists ee=is_expression TArob
{ P.make_cocci_rule_name_result nm d i a e ee }
- | scr=pure_ident TDotDot lang=pure_ident d=depends TArob
- { P.make_script_rule_name_result scr lang d }
+ | TScript TDotDot lang=pure_ident d=depends TArob
+ { P.make_script_rule_name_result lang d }
extends:
/* empty */ { () }
minus_start:
fundecl { [Ast0.wrap(Ast0.DECL($1))] }
| ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
+| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
| toplevel_seq_start(toplevel_after_dots_init)
{ List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1 }
| stm_dots toplevel_after_dots {$1::$2}
| decl_statement toplevel_after_stm {$1@$2}
+top_init:
+ TOInit initialize_list TCBrace
+ { Ast0.wrap(Ast0.InitList(P.clt2mcode "{" $1,$2,P.clt2mcode "}" $3)) }
+
/* ------------------------------------------------------------------------ */
/* Plus top level */
/* does allow only ... also allows multiple top-level functions */
plus_start:
ctype { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
+| top_init { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
| stm_dots plus_after_dots
{ (Ast0.wrap(Ast0.OTHER($1)))::$2 }
| expr plus_after_exp
d=dotter { (d,None) }
| d=dotter TWhen TNotEq w=when_grammar TLineEnd { (d,Some w) }
-dots_when(dotter,when_grammar,simple_when_grammar):
- d=dotter w=list(whens(when_grammar,simple_when_grammar))
- { (d,List.concat w) }
-
whens(when_grammar,simple_when_grammar):
TWhen TNotEq w=when_grammar TLineEnd { [Ast0.WhenNot w] }
| TWhen TEq w=simple_when_grammar TLineEnd { [Ast0.WhenAlways w] }
| TWhen comma_list(any_strict) TLineEnd
{ List.map (function x -> Ast0.WhenModifier(x)) $2 }
+ | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
+ | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
any_strict:
TAny { Ast.WhenAny }
| Ast.Exp(exp) -> print_string arity; expression exp
| Ast.TopExp(exp) -> print_string arity; expression exp
| Ast.Ty(ty) -> print_string arity; fullType ty
+ | Ast.TopInit(init) -> initialiser init
| Ast.Include(inc,s) ->
mcode print_string inc; print_string " "; mcode inc_file s
| Ast.DefineHeader(def,id,params) ->
| Ast.WhenAlways a ->
print_string " WHEN = "; open_box 0; alwaysfn a; close_box()
| Ast.WhenModifier x -> print_string " WHEN "; print_when_modif x
+ | Ast.WhenNotTrue a ->
+ print_string " WHEN != TRUE "; open_box 0; rule_elem "" a; close_box()
+ | Ast.WhenNotFalse a ->
+ print_string " WHEN != FALSE "; open_box 0; rule_elem "" a; close_box()
and print_when_modif = function
| Ast.WhenAny -> print_string "ANY"
| Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
| Ast0.TopExp(exp) -> false (* as above *)
| Ast0.Ty(ty) -> false (* can only be replaced by a type *)
+ | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
| Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
| Ast0.Include(inc,s) -> modif_before_mcode inc
| Ast0.Define(def,id,params,body) -> modif_before_mcode def
| Ast0.Exp(exp) -> false (* can only be replaced by an expression *)
| Ast0.TopExp(exp) -> false (* as above *)
| Ast0.Ty(ty) -> false (* can only be replaced by a type *)
+ | Ast0.TopInit(init) -> false (* can only be replaced by an init *)
| Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> false
| Ast0.Include(inc,s) -> modif_after_mcode s
| Ast0.Define(def,id,params,body) -> right_dots right_statement body
| Ast0.Exp(exp) -> s
| Ast0.TopExp(exp) -> s
| Ast0.Ty(ty) -> s
+ | Ast0.TopInit(init) -> s
| Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) -> s
| Ast0.Include(inc,string) -> s (* doesn't affect the need for braces *)
| Ast0.Define(def,id,params,body) -> s (* same as include *)
| _ -> e)
| _ -> e in
+ let process_wc = function
+ Ast0.WhenNotTrue(e) -> Ast0.WhenNotTrue(process_exp e)
+ | Ast0.WhenNotFalse(e) -> Ast0.WhenNotFalse(process_exp e)
+ | wc -> wc in
+
let statement r k s =
let s = k s in
match Ast0.unwrap s with
| Ast0.For(f,lp,e1,sc1,Some e2,sc2,e3,rp,s1,aft) ->
Ast0.rewrap s
(Ast0.For(f,lp,e1,sc1,Some (process_exp e2),sc2,e3,rp,s1,aft))
+ | Ast0.Dots(d,wc) ->
+ Ast0.rewrap s (Ast0.Dots(d,List.map process_wc wc))
+ | Ast0.Nest(l,s1,r,wc,m) ->
+ Ast0.rewrap s (Ast0.Nest(l,s1,r,List.map process_wc wc,m))
| _ -> s in
V0.rebuilder
| Ast0.OptIdent(id) -> strip id
| Ast0.UniqueIdent(id) -> strip id in
- let process_whencode notfn allfn = function
+ let process_whencode notfn allfn exp = function
Ast0.WhenNot(x) -> let _ = notfn x in ()
| Ast0.WhenAlways(x) -> let _ = allfn x in ()
- | Ast0.WhenModifier(_) -> () in
+ | Ast0.WhenModifier(_) -> ()
+ | Ast0.WhenNotTrue(x) -> let _ = exp x in ()
+ | Ast0.WhenNotFalse(x) -> let _ = exp x in () in
(* assume that all of the declarations are at the beginning of a statement
list, which is required by C, but not actually required by the cocci
let new_acc = (process_decl decl)@acc in
process_statement_list r new_acc ss
| Ast0.Dots(_,wc) ->
+ (* why is this case here? why is there none for nests? *)
List.iter
(process_whencode r.V0.combiner_statement_dots
- r.V0.combiner_statement)
+ r.V0.combiner_statement r.V0.combiner_expression)
wc;
process_statement_list r acc ss
| Ast0.Disj(_,statement_dots_list,_,_) ->
| (_,Ast.Exp(e2)) -> subexp (unify_expression e2) re1
| (Ast.TopExp(e1),Ast.TopExp(e2)) -> unify_expression e1 e2
+ | (Ast.TopInit(i1),Ast.TopInit(i2)) -> unify_initialiser i1 i2
(* can match a rule_elem in different parts *)
| (Ast.Ty(t1),Ast.Ty(t2)) -> return true
List.filter (function x -> not (List.mem x nonunitary)) unitary in
unitary@nonunitary@nonunitary in
- let whencode afn bfn = function
+ let whencode afn bfn expression = function
Ast0.WhenNot(a) -> afn a
| Ast0.WhenAlways(b) -> bfn b
- | Ast0.WhenModifier(_) -> option_default in
+ | Ast0.WhenModifier(_) -> option_default
+ | Ast0.WhenNotTrue(a) -> expression a
+ | Ast0.WhenNotFalse(a) -> expression a in
let ident r k i =
match Ast0.unwrap i with
bind (r.V0.combiner_statement_dots stmt_dots)
(detect_unitary_frees
(List.map
- (whencode r.V0.combiner_statement_dots r.V0.combiner_statement)
+ (whencode r.V0.combiner_statement_dots r.V0.combiner_statement
+ r.V0.combiner_expression)
whn))
| Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
detect_unitary_frees
(List.map
- (whencode r.V0.combiner_statement_dots r.V0.combiner_statement)
+ (whencode r.V0.combiner_statement_dots r.V0.combiner_statement
+ r.V0.combiner_expression)
whn)
| _ -> k s in
| Ast0.Exp(exp) -> print_string arity; expression exp
| Ast0.TopExp(exp) -> print_string arity; expression exp
| Ast0.Ty(ty) -> print_string arity; typeC ty
+ | Ast0.TopInit(init) -> initialiser init
| Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
print_string arity; mcode print_string d;
List.iter
| Ast0.WhenAlways a ->
print_string " WHEN = "; open_box 0; alwaysfn a; close_box()
| Ast0.WhenModifier x -> print_string " WHEN "; U.print_when_modif x
+ | Ast0.WhenNotTrue a ->
+ print_string " WHEN != TRUE "; open_box 0; expression a; close_box()
+ | Ast0.WhenNotFalse a ->
+ print_string " WHEN != FALSE "; open_box 0; expression a; close_box()
and case_line arity c =
print_context c
| Ast0.TopTag(d) ->
top_level d
| Ast0.IsoWhenTag(x) -> U.print_when_modif x
+ | Ast0.IsoWhenTTag(e) -> expression e
+ | Ast0.IsoWhenFTag(e) -> expression e
| Ast0.MetaPosTag(var) -> meta_pos var);
quiet := q;
print_newline()
| Ast.Exp(exp) -> expression exp
| Ast.TopExp(exp) -> expression exp
| Ast.Ty(ty) -> fullType ty
+ | Ast.TopInit(init) -> initialiser init
| Ast.Include(inc,name) -> bind (string_mcode inc) (inc_file_mcode name)
| Ast.DefineHeader(def,id,params) ->
multibind [string_mcode def; ident id; define_parameters params]
Ast.WhenNot a -> notfn a
| Ast.WhenAlways a -> alwaysfn a
| Ast.WhenModifier(_) -> option_default
+ | Ast.WhenNotTrue(e) -> rule_elem e
+ | Ast.WhenNotFalse(e) -> rule_elem e
and case_line c =
let k c =
| Ast.Exp(exp) -> Ast.Exp(expression exp)
| Ast.TopExp(exp) -> Ast.TopExp(expression exp)
| Ast.Ty(ty) -> Ast.Ty(fullType ty)
+ | Ast.TopInit(init) -> Ast.TopInit(initialiser init)
| Ast.Include(inc,name) ->
Ast.Include(string_mcode inc,inc_file_mcode name)
| Ast.DefineHeader(def,id,params) ->
Ast.WhenNot a -> Ast.WhenNot (notfn a)
| Ast.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
| Ast.WhenModifier(x) -> Ast.WhenModifier(x)
+ | Ast.WhenNotTrue(e) -> Ast.WhenNotTrue(rule_elem e)
+ | Ast.WhenNotFalse(e) -> Ast.WhenNotFalse(rule_elem e)
and case_line c =
let k c =
| Ast0.Exp(exp) -> expression exp
| Ast0.TopExp(exp) -> expression exp
| Ast0.Ty(ty) -> typeC ty
+ | Ast0.TopInit(init) -> initialiser init
| Ast0.Dots(d,whn) | Ast0.Circles(d,whn) | Ast0.Stars(d,whn) ->
bind (string_mcode d)
(multibind (List.map (whencode statement_dots statement) whn))
Ast0.WhenNot a -> notfn a
| Ast0.WhenAlways a -> alwaysfn a
| Ast0.WhenModifier(_) -> option_default
+ | Ast0.WhenNotTrue(e) -> expression e
+ | Ast0.WhenNotFalse(e) -> expression e
and case_line c =
let k c =
| Ast0.CaseLineTag(c) -> case_line c
| Ast0.TopTag(top) -> top_level top
| Ast0.IsoWhenTag(_) -> option_default
+ | Ast0.IsoWhenTTag(e) -> expression e
+ | Ast0.IsoWhenFTag(e) -> expression e
| Ast0.MetaPosTag(var) -> failwith "not supported" in
k a
| Ast0.Exp(exp) -> Ast0.Exp(expression exp)
| Ast0.TopExp(exp) -> Ast0.TopExp(expression exp)
| Ast0.Ty(ty) -> Ast0.Ty(typeC ty)
+ | Ast0.TopInit(init) -> Ast0.TopInit(initialiser init)
| Ast0.Dots(d,whn) ->
Ast0.Dots(string_mcode d,
List.map (whencode statement_dots statement) whn)
and whencode notfn alwaysfn = function
Ast0.WhenNot a -> Ast0.WhenNot (notfn a)
| Ast0.WhenAlways a -> Ast0.WhenAlways (alwaysfn a)
- | Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
+ | Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
+ | Ast0.WhenNotTrue(e) -> Ast0.WhenNotTrue(expression e)
+ | Ast0.WhenNotFalse(e) -> Ast0.WhenNotFalse(expression e)
and case_line c =
let k c =
| Ast0.CaseLineTag(c) -> Ast0.CaseLineTag(case_line c)
| Ast0.TopTag(top) -> Ast0.TopTag(top_level top)
| Ast0.IsoWhenTag(x) -> Ast0.IsoWhenTag(x)
+ | Ast0.IsoWhenTTag(e) -> Ast0.IsoWhenTTag(expression e)
+ | Ast0.IsoWhenFTag(e) -> Ast0.IsoWhenFTag(expression e)
| Ast0.MetaPosTag(var) -> failwith "not supported" in
k a
--- /dev/null
+.depend
+*.cma
--- /dev/null
+._d
+pycaml.cma
+pycaml.customtop
--- /dev/null
+.depend
+*.cma
--- /dev/null
+score_cocci_best.marshalled
...
i =@p <+... i ...+>;
-@@
+@x@
identifier s.i;
position s.p0;
position p != r.p;
--- /dev/null
+int main () {
+ f(x);
+ g(x);
+}
+
+int main1 () {
+ f(x);
+ if (x == NULL) {
+ g(x);
+ }
+}
+
+int main1 () {
+ f(x);
+ while (x == NULL) {
+ if (q == 3) {
+ g(x);
+ }
+ }
+ x = 6;
+}
+int main2 () {
+ f(x);
+ if (x == NULL || y == 2) {
+ g(x);
+ }
+}
+
--- /dev/null
+@exists@
+expression x;
+statement S1,S2;
+@@
+
+f(x);
++ after();
+ ... when != true x == NULL || ...
+g(x);
++ after();
+
+@exists@
+expression x;
+statement S1,S2;
+@@
+
++before();
+f(x);
+ ... when != false x == NULL || ...
++before();
+g(x);
--- /dev/null
+int main () {
+ before();
+ f(x);
+ after();
+ before();
+ g(x);
+ after();
+}
+
+int main1 () {
+ before();
+ f(x);
+ if (x == NULL) {
+ before();
+ g(x);
+ }
+}
+
+int main1 () {
+ before();
+ f(x);
+ while (x == NULL) {
+ if (q == 3) {
+ before();
+ g(x);
+ }
+ }
+ x = 6;
+}
+int main2 () {
+ before();
+ f(x);
+ if (x == NULL || y == 2) {
+ before();
+ g(x);
+ }
+}
+
--- /dev/null
+struct a { int a; } x[2] =
+{
+ { .a = 7, },
+ { .a = 17, },
+};
--- /dev/null
+@@
+expression E;
+@@
+
+{
+- .a = E,
++ DECLARE_A(E),
+}
+
--- /dev/null
+struct a { int a; } x[2] =
+{
+ { DECLARE_A(7), },
+ { DECLARE_A(17), },
+};
--- /dev/null
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
+ *
+ * Contributors: "menion?" <menion@mindless.com>
+ * Betatesting, fixes, ideas
+ *
+ * "Kurt Garloff" <garloff@suse.de>
+ * Betatesting, fixes, ideas, videomodes, videomodes timmings
+ *
+ * "Tom Rini" <trini@kernel.crashing.org>
+ * MTRR stuff, PPC cleanups, betatesting, fixes, ideas
+ *
+ * "Bibek Sahu" <scorpio@dodds.net>
+ * Access device through readb|w|l and write b|w|l
+ * Extensive debugging stuff
+ *
+ * "Daniel Haun" <haund@usa.net>
+ * Testing, hardware cursor fixes
+ *
+ * "Scott Wood" <sawst46+@pitt.edu>
+ * Fixes
+ *
+ * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
+ * Betatesting
+ *
+ * "Kelly French" <targon@hazmat.com>
+ * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
+ * Betatesting, bug reporting
+ *
+ * "Pablo Bianucci" <pbian@pccp.com.ar>
+ * Fixes, ideas, betatesting
+ *
+ * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
+ * Fixes, enhandcements, ideas, betatesting
+ *
+ * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
+ * PPC betatesting, PPC support, backward compatibility
+ *
+ * "Paul Womar" <Paul@pwomar.demon.co.uk>
+ * "Owen Waller" <O.Waller@ee.qub.ac.uk>
+ * PPC betatesting
+ *
+ * "Thomas Pornin" <pornin@bolet.ens.fr>
+ * Alpha betatesting
+ *
+ * "Pieter van Leuven" <pvl@iae.nl>
+ * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
+ * G100 testing
+ *
+ * "H. Peter Arvin" <hpa@transmeta.com>
+ * Ideas
+ *
+ * "Cort Dougan" <cort@cs.nmt.edu>
+ * CHRP fixes and PReP cleanup
+ *
+ * "Mark Vojkovich" <mvojkovi@ucsd.edu>
+ * G400 support
+ *
+ * "Samuel Hocevar" <sam@via.ecp.fr>
+ * Fixes
+ *
+ * "Anton Altaparmakov" <AntonA@bigfoot.com>
+ * G400 MAX/non-MAX distinction
+ *
+ * "Ken Aaker" <kdaaker@rchland.vnet.ibm.com>
+ * memtype extension (needed for GXT130P RS/6000 adapter)
+ *
+ * "Uns Lider" <unslider@miranda.org>
+ * G100 PLNWT fixes
+ *
+ * "Denis Zaitsev" <zzz@cd-club.ru>
+ * Fixes
+ *
+ * "Mike Pieper" <mike@pieper-family.de>
+ * TVOut enhandcements, V4L2 control interface.
+ *
+ * "Diego Biurrun" <diego@biurrun.de>
+ * DFP testing
+ *
+ * (following author is not in any relation with this code, but his code
+ * is included in this driver)
+ *
+ * Based on framebuffer driver for VBE 2.0 compliant graphic boards
+ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * (following author is not in any relation with this code, but his ideas
+ * were used when writing this driver)
+ *
+ * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
+ *
+ */
+
+#include <linux/version.h>
+
+#define __OLD_VIDIOC_
+
+#include "matroxfb_base.h"
+#include "matroxfb_misc.h"
+#include "matroxfb_accel.h"
+#include "matroxfb_DAC1064.h"
+#include "matroxfb_Ti3026.h"
+#include "matroxfb_maven.h"
+#include "matroxfb_crtc2.h"
+#include "matroxfb_g450.h"
+#include <linux/matroxfb.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+unsigned char nvram_read_byte(int);
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+#endif
+
+static void matroxfb_unregister_device(struct matrox_fb_info* minfo);
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * card parameters
+ */
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo vesafb_defined = {
+ 640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/
+ 0,0, /* virtual -> visible no offset */
+ 8, /* depth -> load bits_per_pixel */
+ 0, /* greyscale ? */
+ {0,0,0}, /* R */
+ {0,0,0}, /* G */
+ {0,0,0}, /* B */
+ {0,0,0}, /* transparency */
+ 0, /* standard pixel format */
+ FB_ACTIVATE_NOW,
+ -1,-1,
+ FB_ACCELF_TEXT, /* accel flags */
+ 39721L,48L,16L,33L,10L,
+ 96L,2L,~0, /* No sync info */
+ FB_VMODE_NONINTERLACED,
+ 0, {0,0,0,0,0}
+};
+
+
+
+/* --------------------------------------------------------------------- */
+static void update_crtc2(WPMINFO unsigned int pos) {
+ struct matroxfb_dh_fb_info* info = ACCESS_FBINFO(crtc2.info);
+
+ /* Make sure that displays are compatible */
+ if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel)
+ && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
+ && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
+ ) {
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
+ case 16:
+ case 32:
+ pos = pos * 8;
+ if (info->interlaced) {
+ mga_outl(0x3C2C, pos);
+ mga_outl(0x3C28, pos + ACCESS_FBINFO(fbcon).var.xres_virtual * ACCESS_FBINFO(fbcon).var.bits_per_pixel / 8);
+ } else {
+ mga_outl(0x3C28, pos);
+ }
+ break;
+ }
+ }
+}
+
+static void matroxfb_crtc1_panpos(WPMINFO2) {
+ if (ACCESS_FBINFO(crtc1.panpos) >= 0) {
+ unsigned long flags;
+ int panpos;
+
+ matroxfb_DAC_lock_irqsave(flags);
+ panpos = ACCESS_FBINFO(crtc1.panpos);
+ if (panpos >= 0) {
+ unsigned int extvga_reg;
+
+ ACCESS_FBINFO(crtc1.panpos) = -1; /* No update pending anymore */
+ extvga_reg = mga_inb(M_EXTVGA_INDEX);
+ mga_setr(M_EXTVGA_INDEX, 0x00, panpos);
+ if (extvga_reg != 0x00) {
+ mga_outb(M_EXTVGA_INDEX, extvga_reg);
+ }
+ }
+ matroxfb_DAC_unlock_irqrestore(flags);
+ }
+}
+
+static irqreturn_t matrox_irq(int irq, void *dev_id)
+{
+ u_int32_t status;
+ int handled = 0;
+
+ MINFO_FROM(dev_id);
+
+ status = mga_inl(M_STATUS);
+
+ if (status & 0x20) {
+ mga_outl(M_ICLEAR, 0x20);
+ ACCESS_FBINFO(crtc1.vsync.cnt)++;
+ matroxfb_crtc1_panpos(PMINFO2);
+ wake_up_interruptible(&ACCESS_FBINFO(crtc1.vsync.wait));
+ handled = 1;
+ }
+ if (status & 0x200) {
+ mga_outl(M_ICLEAR, 0x200);
+ ACCESS_FBINFO(crtc2.vsync.cnt)++;
+ wake_up_interruptible(&ACCESS_FBINFO(crtc2.vsync.wait));
+ handled = 1;
+ }
+ return IRQ_RETVAL(handled);
+}
+
+int matroxfb_enable_irq(WPMINFO int reenable) {
+ u_int32_t bm;
+
+ if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
+ bm = 0x220;
+ else
+ bm = 0x020;
+
+ if (!test_and_set_bit(0, &ACCESS_FBINFO(irq_flags))) {
+ if (request_irq(ACCESS_FBINFO(pcidev)->irq, matrox_irq,
+ IRQF_SHARED, "matroxfb", MINFO)) {
+ clear_bit(0, &ACCESS_FBINFO(irq_flags));
+ return -EINVAL;
+ }
+ /* Clear any pending field interrupts */
+ mga_outl(M_ICLEAR, bm);
+ mga_outl(M_IEN, mga_inl(M_IEN) | bm);
+ } else if (reenable) {
+ u_int32_t ien;
+
+ ien = mga_inl(M_IEN);
+ if ((ien & bm) != bm) {
+ printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
+ mga_outl(M_IEN, ien | bm);
+ }
+ }
+ return 0;
+}
+
+static void matroxfb_disable_irq(WPMINFO2) {
+ if (test_and_clear_bit(0, &ACCESS_FBINFO(irq_flags))) {
+ /* Flush pending pan-at-vbl request... */
+ matroxfb_crtc1_panpos(PMINFO2);
+ if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
+ mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220);
+ else
+ mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20);
+ free_irq(ACCESS_FBINFO(pcidev)->irq, MINFO);
+ }
+}
+
+int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
+ struct matrox_vsync *vs;
+ unsigned int cnt;
+ int ret;
+
+ switch (crtc) {
+ case 0:
+ vs = &ACCESS_FBINFO(crtc1.vsync);
+ break;
+ case 1:
+ if (ACCESS_FBINFO(devflags.accelerator) != FB_ACCEL_MATROX_MGAG400) {
+ return -ENODEV;
+ }
+ vs = &ACCESS_FBINFO(crtc2.vsync);
+ break;
+ default:
+ return -ENODEV;
+ }
+ ret = matroxfb_enable_irq(PMINFO 0);
+ if (ret) {
+ return ret;
+ }
+
+ cnt = vs->cnt;
+ ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret == 0) {
+ matroxfb_enable_irq(PMINFO 1);
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
+ unsigned int pos;
+ unsigned short p0, p1, p2;
+#ifdef CONFIG_FB_MATROX_32MB
+ unsigned int p3;
+#endif
+ int vbl;
+ unsigned long flags;
+
+ CRITFLAGS
+
+ DBG(__FUNCTION__)
+
+ if (ACCESS_FBINFO(dead))
+ return;
+
+ ACCESS_FBINFO(fbcon).var.xoffset = var->xoffset;
+ ACCESS_FBINFO(fbcon).var.yoffset = var->yoffset;
+ pos = (ACCESS_FBINFO(fbcon).var.yoffset * ACCESS_FBINFO(fbcon).var.xres_virtual + ACCESS_FBINFO(fbcon).var.xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+ pos += ACCESS_FBINFO(curr.ydstorg.chunks);
+ p0 = ACCESS_FBINFO(hw).CRTC[0x0D] = pos & 0xFF;
+ p1 = ACCESS_FBINFO(hw).CRTC[0x0C] = (pos & 0xFF00) >> 8;
+ p2 = ACCESS_FBINFO(hw).CRTCEXT[0] = (ACCESS_FBINFO(hw).CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
+#ifdef CONFIG_FB_MATROX_32MB
+ p3 = ACCESS_FBINFO(hw).CRTCEXT[8] = pos >> 21;
+#endif
+
+ /* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */
+ vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(PMINFO 0) == 0);
+
+ CRITBEGIN
+
+ matroxfb_DAC_lock_irqsave(flags);
+ mga_setr(M_CRTC_INDEX, 0x0D, p0);
+ mga_setr(M_CRTC_INDEX, 0x0C, p1);
+#ifdef CONFIG_FB_MATROX_32MB
+ if (ACCESS_FBINFO(devflags.support32MB))
+ mga_setr(M_EXTVGA_INDEX, 0x08, p3);
+#endif
+ if (vbl) {
+ ACCESS_FBINFO(crtc1.panpos) = p2;
+ } else {
+ /* Abort any pending change */
+ ACCESS_FBINFO(crtc1.panpos) = -1;
+ mga_setr(M_EXTVGA_INDEX, 0x00, p2);
+ }
+ matroxfb_DAC_unlock_irqrestore(flags);
+
+ update_crtc2(PMINFO pos);
+
+ CRITEND
+}
+
+static void matroxfb_remove(WPMINFO int dummy) {
+ /* Currently we are holding big kernel lock on all dead & usecount updates.
+ * Destroy everything after all users release it. Especially do not unregister
+ * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check
+ * for device unplugged when in use.
+ * In future we should point mmio.vbase & video.vbase somewhere where we can
+ * write data without causing too much damage...
+ */
+
+ ACCESS_FBINFO(dead) = 1;
+ if (ACCESS_FBINFO(usecount)) {
+ /* destroy it later */
+ return;
+ }
+ matroxfb_unregister_device(MINFO);
+ unregister_framebuffer(&ACCESS_FBINFO(fbcon));
+ matroxfb_g450_shutdown(PMINFO2);
+#ifdef CONFIG_MTRR
+ if (ACCESS_FBINFO(mtrr.vram_valid))
+ mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len));
+#endif
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+ release_mem_region(ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len_maximum));
+ release_mem_region(ACCESS_FBINFO(mmio.base), 16384);
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ kfree(minfo);
+#endif
+}
+
+ /*
+ * Open/Release the frame buffer device
+ */
+
+static int matroxfb_open(struct fb_info *info, int user)
+{
+ MINFO_FROM_INFO(info);
+
+ DBG_LOOP(__FUNCTION__)
+
+ if (ACCESS_FBINFO(dead)) {
+ return -ENXIO;
+ }
+ ACCESS_FBINFO(usecount)++;
+ if (user) {
+ ACCESS_FBINFO(userusecount)++;
+ }
+ return(0);
+}
+
+static int matroxfb_release(struct fb_info *info, int user)
+{
+ MINFO_FROM_INFO(info);
+
+ DBG_LOOP(__FUNCTION__)
+
+ if (user) {
+ if (0 == --ACCESS_FBINFO(userusecount)) {
+ matroxfb_disable_irq(PMINFO2);
+ }
+ }
+ if (!(--ACCESS_FBINFO(usecount)) && ACCESS_FBINFO(dead)) {
+ matroxfb_remove(PMINFO 0);
+ }
+ return(0);
+}
+
+static int matroxfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info* info) {
+ MINFO_FROM_INFO(info);
+
+ DBG(__FUNCTION__)
+
+ matrox_pan_var(PMINFO var);
+ return 0;
+}
+
+static int matroxfb_get_final_bppShift(CPMINFO int bpp) {
+ int bppshft2;
+
+ DBG(__FUNCTION__)
+
+ bppshft2 = bpp;
+ if (!bppshft2) {
+ return 8;
+ }
+ if (isInterleave(MINFO))
+ bppshft2 >>= 1;
+ if (ACCESS_FBINFO(devflags.video64bits))
+ bppshft2 >>= 1;
+ return bppshft2;
+}
+
+static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) {
+ int over;
+ int rounding;
+
+ DBG(__FUNCTION__)
+
+ switch (bpp) {
+ case 0: return xres;
+ case 4: rounding = 128;
+ break;
+ case 8: rounding = 64; /* doc says 64; 32 is OK for G400 */
+ break;
+ case 16: rounding = 32;
+ break;
+ case 24: rounding = 64; /* doc says 64; 32 is OK for G400 */
+ break;
+ default: rounding = 16;
+ /* on G400, 16 really does not work */
+ if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
+ rounding = 32;
+ break;
+ }
+ if (isInterleave(MINFO)) {
+ rounding *= 2;
+ }
+ over = xres % rounding;
+ if (over)
+ xres += rounding-over;
+ return xres;
+}
+
+static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
+ const int* width;
+ int xres_new;
+
+ DBG(__FUNCTION__)
+
+ if (!bpp) return xres;
+
+ width = ACCESS_FBINFO(capable.vxres);
+
+ if (ACCESS_FBINFO(devflags.precise_width)) {
+ while (*width) {
+ if ((*width >= xres) && (matroxfb_test_and_set_rounding(PMINFO *width, bpp) == *width)) {
+ break;
+ }
+ width++;
+ }
+ xres_new = *width;
+ } else {
+ xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp);
+ }
+ return xres_new;
+}
+
+static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
+
+ DBG(__FUNCTION__)
+
+ switch (var->bits_per_pixel) {
+ case 4:
+ return 16; /* pseudocolor... 16 entries HW palette */
+ case 8:
+ return 256; /* pseudocolor... 256 entries HW palette */
+ case 16:
+ return 16; /* directcolor... 16 entries SW palette */
+ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+ case 24:
+ return 16; /* directcolor... 16 entries SW palette */
+ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+ case 32:
+ return 16; /* directcolor... 16 entries SW palette */
+ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+ }
+ return 16; /* return something reasonable... or panic()? */
+}
+
+static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visual, int *video_cmap_len, unsigned int* ydstorg) {
+ struct RGBT {
+ unsigned char bpp;
+ struct {
+ unsigned char offset,
+ length;
+ } red,
+ green,
+ blue,
+ transp;
+ signed char visual;
+ };
+ static const struct RGBT table[]= {
+ { 8,{ 0,8},{0,8},{0,8},{ 0,0},MX_VISUAL_PSEUDOCOLOR},
+ {15,{10,5},{5,5},{0,5},{15,1},MX_VISUAL_DIRECTCOLOR},
+ {16,{11,5},{5,6},{0,5},{ 0,0},MX_VISUAL_DIRECTCOLOR},
+ {24,{16,8},{8,8},{0,8},{ 0,0},MX_VISUAL_DIRECTCOLOR},
+ {32,{16,8},{8,8},{0,8},{24,8},MX_VISUAL_DIRECTCOLOR}
+ };
+ struct RGBT const *rgbt;
+ unsigned int bpp = var->bits_per_pixel;
+ unsigned int vramlen;
+ unsigned int memlen;
+
+ DBG(__FUNCTION__)
+
+ switch (bpp) {
+ case 4: if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL;
+ break;
+ case 8: break;
+ case 16: break;
+ case 24: break;
+ case 32: break;
+ default: return -EINVAL;
+ }
+ *ydstorg = 0;
+ vramlen = ACCESS_FBINFO(video.len_usable);
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+
+ var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, bpp);
+ memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
+ if (memlen > vramlen) {
+ var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp);
+ memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
+ }
+ /* There is hardware bug that no line can cross 4MB boundary */
+ /* give up for CFB24, it is impossible to easy workaround it */
+ /* for other try to do something */
+ if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000)) {
+ if (bpp == 24) {
+ /* sorry */
+ } else {
+ unsigned int linelen;
+ unsigned int m1 = linelen = var->xres_virtual * bpp / 8;
+ unsigned int m2 = PAGE_SIZE; /* or 128 if you do not need PAGE ALIGNED address */
+ unsigned int max_yres;
+
+ while (m1) {
+ int t;
+
+ while (m2 >= m1) m2 -= m1;
+ t = m1;
+ m1 = m2;
+ m2 = t;
+ }
+ m2 = linelen * PAGE_SIZE / m2;
+ *ydstorg = m2 = 0x400000 % m2;
+ max_yres = (vramlen - m2) / linelen;
+ if (var->yres_virtual > max_yres)
+ var->yres_virtual = max_yres;
+ }
+ }
+ /* YDSTLEN contains only signed 16bit value */
+ if (var->yres_virtual > 32767)
+ var->yres_virtual = 32767;
+ /* we must round yres/xres down, we already rounded y/xres_virtual up
+ if it was possible. We should return -EINVAL, but I disagree */
+ if (var->yres_virtual < var->yres)
+ var->yres = var->yres_virtual;
+ if (var->xres_virtual < var->xres)
+ var->xres = var->xres_virtual;
+ if (var->xoffset + var->xres > var->xres_virtual)
+ var->xoffset = var->xres_virtual - var->xres;
+ if (var->yoffset + var->yres > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+
+ if (bpp == 16 && var->green.length == 5) {
+ bpp--; /* an artifical value - 15 */
+ }
+
+ for (rgbt = table; rgbt->bpp < bpp; rgbt++);
+#define SETCLR(clr)\
+ var->clr.offset = rgbt->clr.offset;\
+ var->clr.length = rgbt->clr.length
+ SETCLR(red);
+ SETCLR(green);
+ SETCLR(blue);
+ SETCLR(transp);
+#undef SETCLR
+ *visual = rgbt->visual;
+
+ if (bpp > 8)
+ dprintk("matroxfb: truecolor: "
+ "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+ var->transp.length, var->red.length, var->green.length, var->blue.length,
+ var->transp.offset, var->red.offset, var->green.offset, var->blue.offset);
+
+ *video_cmap_len = matroxfb_get_cmap_len(var);
+ dprintk(KERN_INFO "requested %d*%d/%dbpp (%d*%d)\n", var->xres, var->yres, var->bits_per_pixel,
+ var->xres_virtual, var->yres_virtual);
+ return 0;
+}
+
+static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info)
+{
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon);
+#endif
+
+ DBG(__FUNCTION__)
+
+ /*
+ * Set a single color register. The values supplied are
+ * already rounded down to the hardware's capabilities
+ * (according to the entries in the `var' structure). Return
+ * != 0 for invalid regno.
+ */
+
+ if (regno >= ACCESS_FBINFO(curr.cmap_len))
+ return 1;
+
+ if (ACCESS_FBINFO(fbcon).var.grayscale) {
+ /* gray = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ red = CNVT_TOHW(red, ACCESS_FBINFO(fbcon).var.red.length);
+ green = CNVT_TOHW(green, ACCESS_FBINFO(fbcon).var.green.length);
+ blue = CNVT_TOHW(blue, ACCESS_FBINFO(fbcon).var.blue.length);
+ transp = CNVT_TOHW(transp, ACCESS_FBINFO(fbcon).var.transp.length);
+
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
+ case 4:
+ case 8:
+ mga_outb(M_DAC_REG, regno);
+ mga_outb(M_DAC_VAL, red);
+ mga_outb(M_DAC_VAL, green);
+ mga_outb(M_DAC_VAL, blue);
+ break;
+ case 16:
+ if (regno >= 16)
+ break;
+ {
+ u_int16_t col =
+ (red << ACCESS_FBINFO(fbcon).var.red.offset) |
+ (green << ACCESS_FBINFO(fbcon).var.green.offset) |
+ (blue << ACCESS_FBINFO(fbcon).var.blue.offset) |
+ (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* for 1:5:5:5 */
+ ACCESS_FBINFO(cmap[regno]) = col | (col << 16);
+ }
+ break;
+ case 24:
+ case 32:
+ if (regno >= 16)
+ break;
+ ACCESS_FBINFO(cmap[regno]) =
+ (red << ACCESS_FBINFO(fbcon).var.red.offset) |
+ (green << ACCESS_FBINFO(fbcon).var.green.offset) |
+ (blue << ACCESS_FBINFO(fbcon).var.blue.offset) |
+ (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* 8:8:8:8 */
+ break;
+ }
+ return 0;
+}
+
+static void matroxfb_init_fix(WPMINFO2)
+{
+ struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix;
+ DBG(__FUNCTION__)
+
+ strcpy(fix->id,"MATROX");
+
+ fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
+ fix->ypanstep = 1;
+ fix->ywrapstep = 0;
+ fix->mmio_start = ACCESS_FBINFO(mmio.base);
+ fix->mmio_len = ACCESS_FBINFO(mmio.len);
+ fix->accel = ACCESS_FBINFO(devflags.accelerator);
+}
+
+static void matroxfb_update_fix(WPMINFO2)
+{
+ struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix;
+ DBG(__FUNCTION__)
+
+ fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
+ fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes);
+}
+
+static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ int err;
+ int visual;
+ int cmap_len;
+ unsigned int ydstorg;
+ MINFO_FROM_INFO(info);
+
+ if (ACCESS_FBINFO(dead)) {
+ return -ENXIO;
+ }
+ if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len, &ydstorg)) != 0)
+ return err;
+ return 0;
+}
+
+static int matroxfb_set_par(struct fb_info *info)
+{
+ int err;
+ int visual;
+ int cmap_len;
+ unsigned int ydstorg;
+ struct fb_var_screeninfo *var;
+ MINFO_FROM_INFO(info);
+
+ DBG(__FUNCTION__)
+
+ if (ACCESS_FBINFO(dead)) {
+ return -ENXIO;
+ }
+
+ var = &info->var;
+ if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len, &ydstorg)) != 0)
+ return err;
+ ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)) + ydstorg;
+ matroxfb_update_fix(PMINFO2);
+ ACCESS_FBINFO(fbcon).fix.visual = visual;
+ ACCESS_FBINFO(fbcon).fix.type = FB_TYPE_PACKED_PIXELS;
+ ACCESS_FBINFO(fbcon).fix.type_aux = 0;
+ ACCESS_FBINFO(fbcon).fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+ {
+ unsigned int pos;
+
+ ACCESS_FBINFO(curr.cmap_len) = cmap_len;
+ ydstorg += ACCESS_FBINFO(devflags.ydstorg);
+ ACCESS_FBINFO(curr.ydstorg.bytes) = ydstorg;
+ ACCESS_FBINFO(curr.ydstorg.chunks) = ydstorg >> (isInterleave(MINFO)?3:2);
+ if (var->bits_per_pixel == 4)
+ ACCESS_FBINFO(curr.ydstorg.pixels) = ydstorg;
+ else
+ ACCESS_FBINFO(curr.ydstorg.pixels) = (ydstorg * 8) / var->bits_per_pixel;
+ ACCESS_FBINFO(curr.final_bppShift) = matroxfb_get_final_bppShift(PMINFO var->bits_per_pixel);
+ { struct my_timming mt;
+ struct matrox_hw_state* hw;
+ int out;
+
+ matroxfb_var2my(var, &mt);
+ mt.crtc = MATROXFB_SRC_CRTC1;
+ /* CRTC1 delays */
+ switch (var->bits_per_pixel) {
+ case 0: mt.delay = 31 + 0; break;
+ case 16: mt.delay = 21 + 8; break;
+ case 24: mt.delay = 17 + 8; break;
+ case 32: mt.delay = 16 + 8; break;
+ default: mt.delay = 31 + 8; break;
+ }
+
+ hw = &ACCESS_FBINFO(hw);
+
+ down_read(&ACCESS_FBINFO(altout).lock);
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 &&
+ ACCESS_FBINFO(outputs[out]).output->compute) {
+ ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt);
+ }
+ }
+ up_read(&ACCESS_FBINFO(altout).lock);
+ ACCESS_FBINFO(crtc1).pixclock = mt.pixclock;
+ ACCESS_FBINFO(crtc1).mnp = mt.mnp;
+ ACCESS_FBINFO(hw_switch->init(PMINFO &mt));
+ pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+ pos += ACCESS_FBINFO(curr.ydstorg.chunks);
+
+ hw->CRTC[0x0D] = pos & 0xFF;
+ hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
+ hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
+ hw->CRTCEXT[8] = pos >> 21;
+ ACCESS_FBINFO(hw_switch->restore(PMINFO2));
+ update_crtc2(PMINFO pos);
+ down_read(&ACCESS_FBINFO(altout).lock);
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 &&
+ ACCESS_FBINFO(outputs[out]).output->program) {
+ ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data);
+ }
+ }
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 &&
+ ACCESS_FBINFO(outputs[out]).output->start) {
+ ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data);
+ }
+ }
+ up_read(&ACCESS_FBINFO(altout).lock);
+ matrox_cfbX_init(PMINFO2);
+ }
+ }
+ ACCESS_FBINFO(initialized) = 1;
+ return 0;
+}
+
+static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank)
+{
+ unsigned int sts1;
+
+ matroxfb_enable_irq(PMINFO 0);
+ memset(vblank, 0, sizeof(*vblank));
+ vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC |
+ FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK;
+ sts1 = mga_inb(M_INSTS1);
+ vblank->vcount = mga_inl(M_VCOUNT);
+ /* BTW, on my PIII/450 with G400, reading M_INSTS1
+ byte makes this call about 12% slower (1.70 vs. 2.05 us
+ per ioctl()) */
+ if (sts1 & 1)
+ vblank->flags |= FB_VBLANK_HBLANKING;
+ if (sts1 & 8)
+ vblank->flags |= FB_VBLANK_VSYNCING;
+ if (vblank->vcount >= ACCESS_FBINFO(fbcon).var.yres)
+ vblank->flags |= FB_VBLANK_VBLANKING;
+ if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {
+ vblank->flags |= FB_VBLANK_HAVE_COUNT;
+ /* Only one writer, aligned int value...
+ it should work without lock and without atomic_t */
+ vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt;
+ }
+ return 0;
+}
+
+static struct matrox_altout panellink_output = {
+ .name = "Panellink output",
+};
+
+static int matroxfb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ MINFO_FROM_INFO(info);
+
+ DBG(__FUNCTION__)
+
+ if (ACCESS_FBINFO(dead)) {
+ return -ENXIO;
+ }
+
+ switch (cmd) {
+ case FBIOGET_VBLANK:
+ {
+ struct fb_vblank vblank;
+ int err;
+
+ err = matroxfb_get_vblank(PMINFO &vblank);
+ if (err)
+ return err;
+ if (copy_to_user(argp, &vblank, sizeof(vblank)))
+ return -EFAULT;
+ return 0;
+ }
+ case FBIO_WAITFORVSYNC:
+ {
+ u_int32_t crt;
+
+ if (get_user(crt, (u_int32_t __user *)arg))
+ return -EFAULT;
+
+ return matroxfb_wait_for_sync(PMINFO crt);
+ }
+ case MATROXFB_SET_OUTPUT_MODE:
+ {
+ struct matroxioc_output_mode mom;
+ struct matrox_altout *oproc;
+ int val;
+
+ if (copy_from_user(&mom, argp, sizeof(mom)))
+ return -EFAULT;
+ if (mom.output >= MATROXFB_MAX_OUTPUTS)
+ return -ENXIO;
+ down_read(&ACCESS_FBINFO(altout.lock));
+ oproc = ACCESS_FBINFO(outputs[mom.output]).output;
+ if (!oproc) {
+ val = -ENXIO;
+ } else if (!oproc->verifymode) {
+ if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) {
+ val = 0;
+ } else {
+ val = -EINVAL;
+ }
+ } else {
+ val = oproc->verifymode(ACCESS_FBINFO(outputs[mom.output]).data, mom.mode);
+ }
+ if (!val) {
+ if (ACCESS_FBINFO(outputs[mom.output]).mode != mom.mode) {
+ ACCESS_FBINFO(outputs[mom.output]).mode = mom.mode;
+ val = 1;
+ }
+ }
+ up_read(&ACCESS_FBINFO(altout.lock));
+ if (val != 1)
+ return val;
+ switch (ACCESS_FBINFO(outputs[mom.output]).src) {
+ case MATROXFB_SRC_CRTC1:
+ matroxfb_set_par(info);
+ break;
+ case MATROXFB_SRC_CRTC2:
+ {
+ struct matroxfb_dh_fb_info* crtc2;
+
+ down_read(&ACCESS_FBINFO(crtc2.lock));
+ crtc2 = ACCESS_FBINFO(crtc2.info);
+ if (crtc2)
+ crtc2->fbcon.fbops->fb_set_par(&crtc2->fbcon);
+ up_read(&ACCESS_FBINFO(crtc2.lock));
+ }
+ break;
+ }
+ return 0;
+ }
+ case MATROXFB_GET_OUTPUT_MODE:
+ {
+ struct matroxioc_output_mode mom;
+ struct matrox_altout *oproc;
+ int val;
+
+ if (copy_from_user(&mom, argp, sizeof(mom)))
+ return -EFAULT;
+ if (mom.output >= MATROXFB_MAX_OUTPUTS)
+ return -ENXIO;
+ down_read(&ACCESS_FBINFO(altout.lock));
+ oproc = ACCESS_FBINFO(outputs[mom.output]).output;
+ if (!oproc) {
+ val = -ENXIO;
+ } else {
+ mom.mode = ACCESS_FBINFO(outputs[mom.output]).mode;
+ val = 0;
+ }
+ up_read(&ACCESS_FBINFO(altout.lock));
+ if (val)
+ return val;
+ if (copy_to_user(argp, &mom, sizeof(mom)))
+ return -EFAULT;
+ return 0;
+ }
+ case MATROXFB_SET_OUTPUT_CONNECTION:
+ {
+ u_int32_t tmp;
+ int i;
+ int changes;
+
+ if (copy_from_user(&tmp, argp, sizeof(tmp)))
+ return -EFAULT;
+ for (i = 0; i < 32; i++) {
+ if (tmp & (1 << i)) {
+ if (i >= MATROXFB_MAX_OUTPUTS)
+ return -ENXIO;
+ if (!ACCESS_FBINFO(outputs[i]).output)
+ return -ENXIO;
+ switch (ACCESS_FBINFO(outputs[i]).src) {
+ case MATROXFB_SRC_NONE:
+ case MATROXFB_SRC_CRTC1:
+ break;
+ default:
+ return -EBUSY;
+ }
+ }
+ }
+ if (ACCESS_FBINFO(devflags.panellink)) {
+ if (tmp & MATROXFB_OUTPUT_CONN_DFP) {
+ if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY)
+ return -EINVAL;
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC2) {
+ return -EBUSY;
+ }
+ }
+ }
+ }
+ changes = 0;
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (tmp & (1 << i)) {
+ if (ACCESS_FBINFO(outputs[i]).src != MATROXFB_SRC_CRTC1) {
+ changes = 1;
+ ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_CRTC1;
+ }
+ } else if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) {
+ changes = 1;
+ ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_NONE;
+ }
+ }
+ if (!changes)
+ return 0;
+ matroxfb_set_par(info);
+ return 0;
+ }
+ case MATROXFB_GET_OUTPUT_CONNECTION:
+ {
+ u_int32_t conn = 0;
+ int i;
+
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) {
+ conn |= 1 << i;
+ }
+ }
+ if (put_user(conn, (u_int32_t __user *)arg))
+ return -EFAULT;
+ return 0;
+ }
+ case MATROXFB_GET_AVAILABLE_OUTPUTS:
+ {
+ u_int32_t conn = 0;
+ int i;
+
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).output) {
+ switch (ACCESS_FBINFO(outputs[i]).src) {
+ case MATROXFB_SRC_NONE:
+ case MATROXFB_SRC_CRTC1:
+ conn |= 1 << i;
+ break;
+ }
+ }
+ }
+ if (ACCESS_FBINFO(devflags.panellink)) {
+ if (conn & MATROXFB_OUTPUT_CONN_DFP)
+ conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
+ if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
+ conn &= ~MATROXFB_OUTPUT_CONN_DFP;
+ }
+ if (put_user(conn, (u_int32_t __user *)arg))
+ return -EFAULT;
+ return 0;
+ }
+ case MATROXFB_GET_ALL_OUTPUTS:
+ {
+ u_int32_t conn = 0;
+ int i;
+
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).output) {
+ conn |= 1 << i;
+ }
+ }
+ if (put_user(conn, (u_int32_t __user *)arg))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability r;
+
+ memset(&r, 0, sizeof(r));
+ strcpy(r.driver, "matroxfb");
+ strcpy(r.card, "Matrox");
+ sprintf(r.bus_info, "PCI:%s", pci_name(ACCESS_FBINFO(pcidev)));
+ r.version = KERNEL_VERSION(1,0,0);
+ r.capabilities = V4L2_CAP_VIDEO_OUTPUT;
+ if (copy_to_user(argp, &r, sizeof(r)))
+ return -EFAULT;
+ return 0;
+
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl qctrl;
+ int err;
+
+ if (copy_from_user(&qctrl, argp, sizeof(qctrl)))
+ return -EFAULT;
+
+ down_read(&ACCESS_FBINFO(altout).lock);
+ if (!ACCESS_FBINFO(outputs[1]).output) {
+ err = -ENXIO;
+ } else if (ACCESS_FBINFO(outputs[1]).output->getqueryctrl) {
+ err = ACCESS_FBINFO(outputs[1]).output->getqueryctrl(ACCESS_FBINFO(outputs[1]).data, &qctrl);
+ } else {
+ err = -EINVAL;
+ }
+ up_read(&ACCESS_FBINFO(altout).lock);
+ if (err >= 0 &&
+ copy_to_user(argp, &qctrl, sizeof(qctrl)))
+ return -EFAULT;
+ return err;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control ctrl;
+ int err;
+
+ if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
+ return -EFAULT;
+
+ down_read(&ACCESS_FBINFO(altout).lock);
+ if (!ACCESS_FBINFO(outputs[1]).output) {
+ err = -ENXIO;
+ } else if (ACCESS_FBINFO(outputs[1]).output->getctrl) {
+ err = ACCESS_FBINFO(outputs[1]).output->getctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl);
+ } else {
+ err = -EINVAL;
+ }
+ up_read(&ACCESS_FBINFO(altout).lock);
+ if (err >= 0 &&
+ copy_to_user(argp, &ctrl, sizeof(ctrl)))
+ return -EFAULT;
+ return err;
+ }
+ case VIDIOC_S_CTRL_OLD:
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control ctrl;
+ int err;
+
+ if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
+ return -EFAULT;
+
+ down_read(&ACCESS_FBINFO(altout).lock);
+ if (!ACCESS_FBINFO(outputs[1]).output) {
+ err = -ENXIO;
+ } else if (ACCESS_FBINFO(outputs[1]).output->setctrl) {
+ err = ACCESS_FBINFO(outputs[1]).output->setctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl);
+ } else {
+ err = -EINVAL;
+ }
+ up_read(&ACCESS_FBINFO(altout).lock);
+ return err;
+ }
+ }
+ return -ENOTTY;
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+
+static int matroxfb_blank(int blank, struct fb_info *info)
+{
+ int seq;
+ int crtc;
+ CRITFLAGS
+ MINFO_FROM_INFO(info);
+
+ DBG(__FUNCTION__)
+
+ if (ACCESS_FBINFO(dead))
+ return 1;
+
+ switch (blank) {
+ case FB_BLANK_NORMAL: seq = 0x20; crtc = 0x00; break; /* works ??? */
+ case FB_BLANK_VSYNC_SUSPEND: seq = 0x20; crtc = 0x10; break;
+ case FB_BLANK_HSYNC_SUSPEND: seq = 0x20; crtc = 0x20; break;
+ case FB_BLANK_POWERDOWN: seq = 0x20; crtc = 0x30; break;
+ default: seq = 0x00; crtc = 0x00; break;
+ }
+
+ CRITBEGIN
+
+ mga_outb(M_SEQ_INDEX, 1);
+ mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq);
+ mga_outb(M_EXTVGA_INDEX, 1);
+ mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc);
+
+ CRITEND
+ return 0;
+}
+
+static struct fb_ops matroxfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = matroxfb_open,
+ .fb_release = matroxfb_release,
+ .fb_check_var = matroxfb_check_var,
+ .fb_set_par = matroxfb_set_par,
+ .fb_setcolreg = matroxfb_setcolreg,
+ .fb_pan_display =matroxfb_pan_display,
+ .fb_blank = matroxfb_blank,
+ .fb_ioctl = matroxfb_ioctl,
+/* .fb_fillrect = <set by matrox_cfbX_init>, */
+/* .fb_copyarea = <set by matrox_cfbX_init>, */
+/* .fb_imageblit = <set by matrox_cfbX_init>, */
+/* .fb_cursor = <set by matrox_cfbX_init>, */
+};
+
+#define RSDepth(X) (((X) >> 8) & 0x0F)
+#define RS8bpp 0x1
+#define RS15bpp 0x2
+#define RS16bpp 0x3
+#define RS32bpp 0x4
+#define RS4bpp 0x5
+#define RS24bpp 0x6
+#define RSText 0x7
+#define RSText8 0x8
+/* 9-F */
+static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; } colors[] = {
+ { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 8 },
+ { { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
+ { { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0}, { 0, 0, 0}, 16 },
+ { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
+ { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 4 },
+ { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 24 },
+ { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode with (default) VGA8x16 */
+ { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode hardwired to VGA8x8 */
+};
+
+/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
+static unsigned int mem; /* "matrox:mem:xxxxxM" */
+static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */
+static int inv24; /* "matrox:inv24" */
+static int cross4MB = -1; /* "matrox:cross4MB" */
+static int disabled; /* "matrox:disabled" */
+static int noaccel; /* "matrox:noaccel" */
+static int nopan; /* "matrox:nopan" */
+static int no_pci_retry; /* "matrox:nopciretry" */
+static int novga; /* "matrox:novga" */
+static int nobios; /* "matrox:nobios" */
+static int noinit = 1; /* "matrox:init" */
+static int inverse; /* "matrox:inverse" */
+static int sgram; /* "matrox:sgram" */
+#ifdef CONFIG_MTRR
+static int mtrr = 1; /* "matrox:nomtrr" */
+#endif
+static int grayscale; /* "matrox:grayscale" */
+static int dev = -1; /* "matrox:dev:xxxxx" */
+static unsigned int vesa = ~0; /* "matrox:vesa:xxxxx" */
+static int depth = -1; /* "matrox:depth:xxxxx" */
+static unsigned int xres; /* "matrox:xres:xxxxx" */
+static unsigned int yres; /* "matrox:yres:xxxxx" */
+static unsigned int upper = ~0; /* "matrox:upper:xxxxx" */
+static unsigned int lower = ~0; /* "matrox:lower:xxxxx" */
+static unsigned int vslen; /* "matrox:vslen:xxxxx" */
+static unsigned int left = ~0; /* "matrox:left:xxxxx" */
+static unsigned int right = ~0; /* "matrox:right:xxxxx" */
+static unsigned int hslen; /* "matrox:hslen:xxxxx" */
+static unsigned int pixclock; /* "matrox:pixclock:xxxxx" */
+static int sync = -1; /* "matrox:sync:xxxxx" */
+static unsigned int fv; /* "matrox:fv:xxxxx" */
+static unsigned int fh; /* "matrox:fh:xxxxxk" */
+static unsigned int maxclk; /* "matrox:maxclk:xxxxM" */
+static int dfp; /* "matrox:dfp */
+static int dfp_type = -1; /* "matrox:dfp:xxx */
+static int memtype = -1; /* "matrox:memtype:xxx" */
+static char outputs[8]; /* "matrox:outputs:xxx" */
+
+#ifndef MODULE
+static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */
+#endif
+
+static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSize){
+ vaddr_t vm;
+ unsigned int offs;
+ unsigned int offs2;
+ unsigned char orig;
+ unsigned char bytes[32];
+ unsigned char* tmp;
+
+ DBG(__FUNCTION__)
+
+ vm = ACCESS_FBINFO(video.vbase);
+ maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */
+ /* at least 2MB */
+ if (maxSize < 0x0200000) return 0;
+ if (maxSize > 0x2000000) maxSize = 0x2000000;
+
+ mga_outb(M_EXTVGA_INDEX, 0x03);
+ orig = mga_inb(M_EXTVGA_DATA);
+ mga_outb(M_EXTVGA_DATA, orig | 0x80);
+
+ tmp = bytes;
+ for (offs = 0x100000; offs < maxSize; offs += 0x200000)
+ *tmp++ = mga_readb(vm, offs);
+ for (offs = 0x100000; offs < maxSize; offs += 0x200000)
+ mga_writeb(vm, offs, 0x02);
+ mga_outb(M_CACHEFLUSH, 0x00);
+ for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
+ if (mga_readb(vm, offs) != 0x02)
+ break;
+ mga_writeb(vm, offs, mga_readb(vm, offs) - 0x02);
+ if (mga_readb(vm, offs))
+ break;
+ }
+ tmp = bytes;
+ for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
+ mga_writeb(vm, offs2, *tmp++);
+
+ mga_outb(M_EXTVGA_INDEX, 0x03);
+ mga_outb(M_EXTVGA_DATA, orig);
+
+ *realSize = offs - 0x100000;
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+ ACCESS_FBINFO(interleave) = !(!isMillenium(MINFO) || ((offs - 0x100000) & 0x3FFFFF));
+#endif
+ return 1;
+}
+
+struct video_board {
+ int maxvram;
+ int maxdisplayable;
+ int accelID;
+ struct matrox_switch* lowlevel;
+ };
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static struct video_board vbMillennium = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA2064W, &matrox_millennium};
+static struct video_board vbMillennium2 = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W, &matrox_millennium};
+static struct video_board vbMillennium2A = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W_AGP, &matrox_millennium};
+#endif /* CONFIG_FB_MATROX_MILLENIUM */
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static struct video_board vbMystique = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG, &matrox_mystique};
+#endif /* CONFIG_FB_MATROX_MYSTIQUE */
+#ifdef CONFIG_FB_MATROX_G
+static struct video_board vbG100 = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100};
+static struct video_board vbG200 = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100};
+#ifdef CONFIG_FB_MATROX_32MB
+/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
+ whole 32MB */
+static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100};
+#else
+static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100};
+#endif
+#endif
+
+#define DEVF_VIDEO64BIT 0x0001
+#define DEVF_SWAPS 0x0002
+#define DEVF_SRCORG 0x0004
+#define DEVF_DUALHEAD 0x0008
+#define DEVF_CROSS4MB 0x0010
+#define DEVF_TEXT4B 0x0020
+/* #define DEVF_recycled 0x0040 */
+/* #define DEVF_recycled 0x0080 */
+#define DEVF_SUPPORT32MB 0x0100
+#define DEVF_ANY_VXRES 0x0200
+#define DEVF_TEXT16B 0x0400
+#define DEVF_CRTC2 0x0800
+#define DEVF_MAVEN_CAPABLE 0x1000
+#define DEVF_PANELLINK_CAPABLE 0x2000
+#define DEVF_G450DAC 0x4000
+
+#define DEVF_GCORE (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB)
+#define DEVF_G2CORE (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE | DEVF_SRCORG | DEVF_DUALHEAD)
+#define DEVF_G100 (DEVF_GCORE) /* no doc, no vxres... */
+#define DEVF_G200 (DEVF_G2CORE)
+#define DEVF_G400 (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2)
+/* if you'll find how to drive DFP... */
+#define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG | DEVF_DUALHEAD)
+#define DEVF_G550 (DEVF_G450)
+
+static struct board {
+ unsigned short vendor, device, rev, svid, sid;
+ unsigned int flags;
+ unsigned int maxclk;
+ enum mga_chip chip;
+ struct video_board* base;
+ const char* name;
+ } dev_list[] = {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL, 0xFF,
+ 0, 0,
+ DEVF_TEXT4B,
+ 230000,
+ MGA_2064,
+ &vbMillennium,
+ "Millennium (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2, 0xFF,
+ 0, 0,
+ DEVF_SWAPS,
+ 220000,
+ MGA_2164,
+ &vbMillennium2,
+ "Millennium II (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP, 0xFF,
+ 0, 0,
+ DEVF_SWAPS,
+ 250000,
+ MGA_2164,
+ &vbMillennium2A,
+ "Millennium II (AGP)"},
+#endif
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0x02,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_CROSS4MB,
+ 180000,
+ MGA_1064,
+ &vbMystique,
+ "Mystique (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ MGA_1164,
+ &vbMystique,
+ "Mystique 220 (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0x02,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_CROSS4MB,
+ 180000,
+ MGA_1064,
+ &vbMystique,
+ "Mystique (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ MGA_1164,
+ &vbMystique,
+ "Mystique 220 (AGP)"},
+#endif
+#ifdef CONFIG_FB_MATROX_G
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF,
+ 0, 0,
+ DEVF_G100,
+ 230000,
+ MGA_G100,
+ &vbG100,
+ "MGA-G100 (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
+ 0, 0,
+ DEVF_G100,
+ 230000,
+ MGA_G100,
+ &vbG100,
+ "MGA-G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF,
+ 0, 0,
+ DEVF_G200,
+ 250000,
+ MGA_G200,
+ &vbG200,
+ "MGA-G200 (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
+ DEVF_G200,
+ 220000,
+ MGA_G200,
+ &vbG200,
+ "MGA-G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
+ DEVF_G200,
+ 230000,
+ MGA_G200,
+ &vbG200,
+ "Mystique G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENIUM_G200_AGP,
+ DEVF_G200,
+ 250000,
+ MGA_G200,
+ &vbG200,
+ "Millennium G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MARVEL_G200_AGP,
+ DEVF_G200,
+ 230000,
+ MGA_G200,
+ &vbG200,
+ "Marvel G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G200_AGP,
+ DEVF_G200,
+ 230000,
+ MGA_G200,
+ &vbG200,
+ "MGA-G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ 0, 0,
+ DEVF_G200,
+ 230000,
+ MGA_G200,
+ &vbG200,
+ "G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP,
+ DEVF_G400,
+ 360000,
+ MGA_G400,
+ &vbG400,
+ "Millennium G400 MAX (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80,
+ 0, 0,
+ DEVF_G400,
+ 300000,
+ MGA_G400,
+ &vbG400,
+ "G400 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0xFF,
+ 0, 0,
+ DEVF_G450,
+ 360000,
+ MGA_G450,
+ &vbG400,
+ "G450"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G550, 0xFF,
+ 0, 0,
+ DEVF_G550,
+ 360000,
+ MGA_G550,
+ &vbG400,
+ "G550"},
+#endif
+ {0, 0, 0xFF,
+ 0, 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL}};
+
+#ifndef MODULE
+static struct fb_videomode defaultmode = {
+ /* 640x480 @ 60Hz, 31.5 kHz */
+ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+ 0, FB_VMODE_NONINTERLACED
+};
+#endif /* !MODULE */
+
+static int hotplug = 0;
+
+static void setDefaultOutputs(WPMINFO2) {
+ unsigned int i;
+ const char* ptr;
+
+ ACCESS_FBINFO(outputs[0]).default_src = MATROXFB_SRC_CRTC1;
+ if (ACCESS_FBINFO(devflags.g450dac)) {
+ ACCESS_FBINFO(outputs[1]).default_src = MATROXFB_SRC_CRTC1;
+ ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1;
+ } else if (dfp) {
+ ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1;
+ }
+ ptr = outputs;
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ char c = *ptr++;
+
+ if (c == 0) {
+ break;
+ }
+ if (c == '0') {
+ ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_NONE;
+ } else if (c == '1') {
+ ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC1;
+ } else if (c == '2' && ACCESS_FBINFO(devflags.crtc2)) {
+ ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC2;
+ } else {
+ printk(KERN_ERR "matroxfb: Unknown outputs setting\n");
+ break;
+ }
+ }
+ /* Nullify this option for subsequent adapters */
+ outputs[0] = 0;
+}
+
+static int initMatrox2(WPMINFO struct board* b){
+ unsigned long ctrlptr_phys = 0;
+ unsigned long video_base_phys = 0;
+ unsigned int memsize;
+ int err;
+
+ static struct pci_device_id intel_82437[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437) },
+ { },
+ };
+
+ DBG(__FUNCTION__)
+
+ /* set default values... */
+ vesafb_defined.accel_flags = FB_ACCELF_TEXT;
+
+ ACCESS_FBINFO(hw_switch) = b->base->lowlevel;
+ ACCESS_FBINFO(devflags.accelerator) = b->base->accelID;
+ ACCESS_FBINFO(max_pixel_clock) = b->maxclk;
+
+ printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
+ ACCESS_FBINFO(capable.plnwt) = 1;
+ ACCESS_FBINFO(chip) = b->chip;
+ ACCESS_FBINFO(capable.srcorg) = b->flags & DEVF_SRCORG;
+ ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT;
+ if (b->flags & DEVF_TEXT4B) {
+ ACCESS_FBINFO(devflags.vgastep) = 4;
+ ACCESS_FBINFO(devflags.textmode) = 4;
+ ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16;
+ } else if (b->flags & DEVF_TEXT16B) {
+ ACCESS_FBINFO(devflags.vgastep) = 16;
+ ACCESS_FBINFO(devflags.textmode) = 1;
+ ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16;
+ } else {
+ ACCESS_FBINFO(devflags.vgastep) = 8;
+ ACCESS_FBINFO(devflags.textmode) = 1;
+ ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8;
+ }
+#ifdef CONFIG_FB_MATROX_32MB
+ ACCESS_FBINFO(devflags.support32MB) = (b->flags & DEVF_SUPPORT32MB) != 0;
+#endif
+ ACCESS_FBINFO(devflags.precise_width) = !(b->flags & DEVF_ANY_VXRES);
+ ACCESS_FBINFO(devflags.crtc2) = (b->flags & DEVF_CRTC2) != 0;
+ ACCESS_FBINFO(devflags.maven_capable) = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
+ ACCESS_FBINFO(devflags.dualhead) = (b->flags & DEVF_DUALHEAD) != 0;
+ ACCESS_FBINFO(devflags.dfp_type) = dfp_type;
+ ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0;
+ ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
+ ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
+ setDefaultOutputs(PMINFO2);
+ if (b->flags & DEVF_PANELLINK_CAPABLE) {
+ ACCESS_FBINFO(outputs[2]).data = MINFO;
+ ACCESS_FBINFO(outputs[2]).output = &panellink_output;
+ ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src;
+ ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+ ACCESS_FBINFO(devflags.panellink) = 1;
+ }
+
+ if (ACCESS_FBINFO(capable.cross4MB) < 0)
+ ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
+ if (b->flags & DEVF_SWAPS) {
+ ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1);
+ video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0);
+ ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_0;
+ } else {
+ ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0);
+ video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1);
+ ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_1;
+ }
+ err = -EINVAL;
+ if (!ctrlptr_phys) {
+ printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n");
+ goto fail;
+ }
+ if (!video_base_phys) {
+ printk(KERN_ERR "matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
+ goto fail;
+ }
+ memsize = b->base->maxvram;
+ if (!request_mem_region(ctrlptr_phys, 16384, "matroxfb MMIO")) {
+ goto fail;
+ }
+ if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) {
+ goto failCtrlMR;
+ }
+ ACCESS_FBINFO(video.len_maximum) = memsize;
+ /* convert mem (autodetect k, M) */
+ if (mem < 1024) mem *= 1024;
+ if (mem < 0x00100000) mem *= 1024;
+
+ if (mem && (mem < memsize))
+ memsize = mem;
+ err = -ENOMEM;
+ if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &ACCESS_FBINFO(mmio.vbase))) {
+ printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
+ goto failVideoMR;
+ }
+ ACCESS_FBINFO(mmio.base) = ctrlptr_phys;
+ ACCESS_FBINFO(mmio.len) = 16384;
+ ACCESS_FBINFO(video.base) = video_base_phys;
+ if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) {
+ printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
+ video_base_phys, memsize);
+ goto failCtrlIO;
+ }
+ {
+ u_int32_t cmd;
+ u_int32_t mga_option;
+
+ pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &mga_option);
+ pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd);
+ mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
+ mga_option |= MX_OPTION_BSWAP;
+ /* disable palette snooping */
+ cmd &= ~PCI_COMMAND_VGA_PALETTE;
+ if (pci_dev_present(intel_82437)) {
+ if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) {
+ printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
+ }
+ mga_option |= 0x20000000;
+ ACCESS_FBINFO(devflags.nopciretry) = 1;
+ }
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, cmd);
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mga_option);
+ ACCESS_FBINFO(hw).MXoptionReg = mga_option;
+
+ /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
+ /* maybe preinit() candidate, but it is same... for all devices... at this time... */
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MGA_INDEX, 0x00003C00);
+ }
+
+ err = -ENXIO;
+ matroxfb_read_pins(PMINFO2);
+ if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO2)) {
+ goto failVideoIO;
+ }
+
+ err = -ENOMEM;
+ if (!matroxfb_getmemory(PMINFO memsize, &ACCESS_FBINFO(video.len)) || !ACCESS_FBINFO(video.len)) {
+ printk(KERN_ERR "matroxfb: cannot determine memory size\n");
+ goto failVideoIO;
+ }
+ ACCESS_FBINFO(devflags.ydstorg) = 0;
+
+ ACCESS_FBINFO(video.base) = video_base_phys;
+ ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len);
+ if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable)
+ ACCESS_FBINFO(video.len_usable) = b->base->maxdisplayable;
+#ifdef CONFIG_MTRR
+ if (mtrr) {
+ ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
+ ACCESS_FBINFO(mtrr.vram_valid) = 1;
+ printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+ }
+#endif /* CONFIG_MTRR */
+
+ if (!ACCESS_FBINFO(devflags.novga))
+ request_region(0x3C0, 32, "matrox");
+ matroxfb_g450_connect(PMINFO2);
+ ACCESS_FBINFO(hw_switch->reset(PMINFO2));
+
+ ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0;
+ ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh;
+ ACCESS_FBINFO(fbcon.monspecs.vfmin) = 0;
+ ACCESS_FBINFO(fbcon.monspecs.vfmax) = fv;
+ ACCESS_FBINFO(fbcon.monspecs.dpms) = 0; /* TBD */
+
+ /* static settings */
+ vesafb_defined.red = colors[depth-1].red;
+ vesafb_defined.green = colors[depth-1].green;
+ vesafb_defined.blue = colors[depth-1].blue;
+ vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel;
+ vesafb_defined.grayscale = grayscale;
+ vesafb_defined.vmode = 0;
+ if (noaccel)
+ vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
+
+ ACCESS_FBINFO(fbops) = matroxfb_ops;
+ ACCESS_FBINFO(fbcon.fbops) = &ACCESS_FBINFO(fbops);
+ ACCESS_FBINFO(fbcon.pseudo_palette) = ACCESS_FBINFO(cmap);
+ /* after __init time we are like module... no logo */
+ ACCESS_FBINFO(fbcon.flags) = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT;
+ ACCESS_FBINFO(fbcon.flags) |= FBINFO_PARTIAL_PAN_OK | /* Prefer panning for scroll under MC viewer/edit */
+ FBINFO_HWACCEL_COPYAREA | /* We have hw-assisted bmove */
+ FBINFO_HWACCEL_FILLRECT | /* And fillrect */
+ FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */
+ FBINFO_HWACCEL_XPAN | /* And we support both horizontal */
+ FBINFO_HWACCEL_YPAN; /* And vertical panning */
+ ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
+ fb_alloc_cmap(&ACCESS_FBINFO(fbcon.cmap), 256, 1);
+
+#ifndef MODULE
+ /* mode database is marked __init!!! */
+ if (!hotplug) {
+ fb_find_mode(&vesafb_defined, &ACCESS_FBINFO(fbcon), videomode[0]?videomode:NULL,
+ NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
+ }
+#endif /* !MODULE */
+
+ /* mode modifiers */
+ if (hslen)
+ vesafb_defined.hsync_len = hslen;
+ if (vslen)
+ vesafb_defined.vsync_len = vslen;
+ if (left != ~0)
+ vesafb_defined.left_margin = left;
+ if (right != ~0)
+ vesafb_defined.right_margin = right;
+ if (upper != ~0)
+ vesafb_defined.upper_margin = upper;
+ if (lower != ~0)
+ vesafb_defined.lower_margin = lower;
+ if (xres)
+ vesafb_defined.xres = xres;
+ if (yres)
+ vesafb_defined.yres = yres;
+ if (sync != -1)
+ vesafb_defined.sync = sync;
+ else if (vesafb_defined.sync == ~0) {
+ vesafb_defined.sync = 0;
+ if (yres < 400)
+ vesafb_defined.sync |= FB_SYNC_HOR_HIGH_ACT;
+ else if (yres < 480)
+ vesafb_defined.sync |= FB_SYNC_VERT_HIGH_ACT;
+ }
+
+ /* fv, fh, maxclk limits was specified */
+ {
+ unsigned int tmp;
+
+ if (fv) {
+ tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
+ + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
+ if ((tmp < fh) || (fh == 0)) fh = tmp;
+ }
+ if (fh) {
+ tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
+ + vesafb_defined.right_margin + vesafb_defined.hsync_len);
+ if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
+ }
+ tmp = (maxclk + 499) / 500;
+ if (tmp) {
+ tmp = (2000000000 + tmp) / tmp;
+ if (tmp > pixclock) pixclock = tmp;
+ }
+ }
+ if (pixclock) {
+ if (pixclock < 2000) /* > 500MHz */
+ pixclock = 4000; /* 250MHz */
+ if (pixclock > 1000000)
+ pixclock = 1000000; /* 1MHz */
+ vesafb_defined.pixclock = pixclock;
+ }
+
+ /* FIXME: Where to move this?! */
+#if defined(CONFIG_PPC_PMAC)
+#ifndef MODULE
+ if (machine_is(powermac)) {
+ struct fb_var_screeninfo var;
+ if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+ default_vmode = VMODE_640_480_60;
+#ifdef CONFIG_NVRAM
+ if (default_cmode == CMODE_NVRAM)
+ default_cmode = nvram_read_byte(NV_CMODE);
+#endif
+ if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+ default_cmode = CMODE_8;
+ if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
+ var.accel_flags = vesafb_defined.accel_flags;
+ var.xoffset = var.yoffset = 0;
+ /* Note: mac_vmode_to_var() does not set all parameters */
+ vesafb_defined = var;
+ }
+ }
+#endif /* !MODULE */
+#endif /* CONFIG_PPC_PMAC */
+ vesafb_defined.xres_virtual = vesafb_defined.xres;
+ if (nopan) {
+ vesafb_defined.yres_virtual = vesafb_defined.yres;
+ } else {
+ vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
+ to yres_virtual * xres_virtual < 2^32 */
+ }
+ matroxfb_init_fix(PMINFO2);
+ ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
+ matroxfb_update_fix(PMINFO2);
+ /* Normalize values (namely yres_virtual) */
+ matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
+ /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
+ * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
+ * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
+ * anyway. But we at least tried... */
+ ACCESS_FBINFO(fbcon.var) = vesafb_defined;
+ err = -EINVAL;
+
+ printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
+ vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
+ vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
+ printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
+ ACCESS_FBINFO(video.base), vaddr_va(ACCESS_FBINFO(video.vbase)), ACCESS_FBINFO(video.len));
+
+/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
+ * and we do not want currcon == 0 for subsequent framebuffers */
+
+ ACCESS_FBINFO(fbcon).device = &ACCESS_FBINFO(pcidev)->dev;
+ if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0) {
+ goto failVideoIO;
+ }
+ printk("fb%d: %s frame buffer device\n",
+ ACCESS_FBINFO(fbcon.node), ACCESS_FBINFO(fbcon.fix.id));
+
+ /* there is no console on this fb... but we have to initialize hardware
+ * until someone tells me what is proper thing to do */
+ if (!ACCESS_FBINFO(initialized)) {
+ printk(KERN_INFO "fb%d: initializing hardware\n",
+ ACCESS_FBINFO(fbcon.node));
+ /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
+ * already before, so register_framebuffer works correctly. */
+ vesafb_defined.activate |= FB_ACTIVATE_FORCE;
+ fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
+ }
+
+ return 0;
+failVideoIO:;
+ matroxfb_g450_shutdown(PMINFO2);
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+failCtrlIO:;
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+failVideoMR:;
+ release_mem_region(video_base_phys, ACCESS_FBINFO(video.len_maximum));
+failCtrlMR:;
+ release_mem_region(ctrlptr_phys, 16384);
+fail:;
+ return err;
+}
+
+static LIST_HEAD(matroxfb_list);
+static LIST_HEAD(matroxfb_driver_list);
+
+#define matroxfb_l(x) list_entry(x, struct matrox_fb_info, next_fb)
+#define matroxfb_driver_l(x) list_entry(x, struct matroxfb_driver, node)
+int matroxfb_register_driver(struct matroxfb_driver* drv) {
+ struct matrox_fb_info* minfo;
+
+ list_add(&drv->node, &matroxfb_driver_list);
+ for (minfo = matroxfb_l(matroxfb_list.next);
+ minfo != matroxfb_l(&matroxfb_list);
+ minfo = matroxfb_l(minfo->next_fb.next)) {
+ void* p;
+
+ if (minfo->drivers_count == MATROXFB_MAX_FB_DRIVERS)
+ continue;
+ p = drv->probe(minfo);
+ if (p) {
+ minfo->drivers_data[minfo->drivers_count] = p;
+ minfo->drivers[minfo->drivers_count++] = drv;
+ }
+ }
+ return 0;
+}
+
+void matroxfb_unregister_driver(struct matroxfb_driver* drv) {
+ struct matrox_fb_info* minfo;
+
+ list_del(&drv->node);
+ for (minfo = matroxfb_l(matroxfb_list.next);
+ minfo != matroxfb_l(&matroxfb_list);
+ minfo = matroxfb_l(minfo->next_fb.next)) {
+ int i;
+
+ for (i = 0; i < minfo->drivers_count; ) {
+ if (minfo->drivers[i] == drv) {
+ if (drv && drv->remove)
+ drv->remove(minfo, minfo->drivers_data[i]);
+ minfo->drivers[i] = minfo->drivers[--minfo->drivers_count];
+ minfo->drivers_data[i] = minfo->drivers_data[minfo->drivers_count];
+ } else
+ i++;
+ }
+ }
+}
+
+static void matroxfb_register_device(struct matrox_fb_info* minfo) {
+ struct matroxfb_driver* drv;
+ int i = 0;
+ list_add(&ACCESS_FBINFO(next_fb), &matroxfb_list);
+ for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
+ drv != matroxfb_driver_l(&matroxfb_driver_list);
+ drv = matroxfb_driver_l(drv->node.next)) {
+ if (drv && drv->probe) {
+ void *p = drv->probe(minfo);
+ if (p) {
+ minfo->drivers_data[i] = p;
+ minfo->drivers[i++] = drv;
+ if (i == MATROXFB_MAX_FB_DRIVERS)
+ break;
+ }
+ }
+ }
+ minfo->drivers_count = i;
+}
+
+static void matroxfb_unregister_device(struct matrox_fb_info* minfo) {
+ int i;
+
+ list_del(&ACCESS_FBINFO(next_fb));
+ for (i = 0; i < minfo->drivers_count; i++) {
+ struct matroxfb_driver* drv = minfo->drivers[i];
+
+ if (drv && drv->remove)
+ drv->remove(minfo, minfo->drivers_data[i]);
+ }
+}
+
+static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dummy) {
+ struct board* b;
+ u_int16_t svid;
+ u_int16_t sid;
+ struct matrox_fb_info* minfo;
+ int err;
+ u_int32_t cmd;
+#ifndef CONFIG_FB_MATROX_MULTIHEAD
+ static int registered = 0;
+#endif
+ DBG(__FUNCTION__)
+
+ svid = pdev->subsystem_vendor;
+ sid = pdev->subsystem_device;
+ for (b = dev_list; b->vendor; b++) {
+ if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < pdev->revision)) continue;
+ if (b->svid)
+ if ((b->svid != svid) || (b->sid != sid)) continue;
+ break;
+ }
+ /* not match... */
+ if (!b->vendor)
+ return -ENODEV;
+ if (dev > 0) {
+ /* not requested one... */
+ dev--;
+ return -ENODEV;
+ }
+ pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+ if (pci_enable_device(pdev)) {
+ return -1;
+ }
+
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
+ if (!minfo)
+ return -1;
+#else
+ if (registered) /* singlehead driver... */
+ return -1;
+ minfo = &matroxfb_global_mxinfo;
+#endif
+ memset(MINFO, 0, sizeof(*MINFO));
+
+ ACCESS_FBINFO(pcidev) = pdev;
+ ACCESS_FBINFO(dead) = 0;
+ ACCESS_FBINFO(usecount) = 0;
+ ACCESS_FBINFO(userusecount) = 0;
+
+ pci_set_drvdata(pdev, MINFO);
+ /* DEVFLAGS */
+ ACCESS_FBINFO(devflags.memtype) = memtype;
+ if (memtype != -1)
+ noinit = 0;
+ if (cmd & PCI_COMMAND_MEMORY) {
+ ACCESS_FBINFO(devflags.novga) = novga;
+ ACCESS_FBINFO(devflags.nobios) = nobios;
+ ACCESS_FBINFO(devflags.noinit) = noinit;
+ /* subsequent heads always needs initialization and must not enable BIOS */
+ novga = 1;
+ nobios = 1;
+ noinit = 0;
+ } else {
+ ACCESS_FBINFO(devflags.novga) = 1;
+ ACCESS_FBINFO(devflags.nobios) = 1;
+ ACCESS_FBINFO(devflags.noinit) = 0;
+ }
+
+ ACCESS_FBINFO(devflags.nopciretry) = no_pci_retry;
+ ACCESS_FBINFO(devflags.mga_24bpp_fix) = inv24;
+ ACCESS_FBINFO(devflags.precise_width) = option_precise_width;
+ ACCESS_FBINFO(devflags.sgram) = sgram;
+ ACCESS_FBINFO(capable.cross4MB) = cross4MB;
+
+ spin_lock_init(&ACCESS_FBINFO(lock.DAC));
+ spin_lock_init(&ACCESS_FBINFO(lock.accel));
+ init_rwsem(&ACCESS_FBINFO(crtc2.lock));
+ init_rwsem(&ACCESS_FBINFO(altout.lock));
+ ACCESS_FBINFO(irq_flags) = 0;
+ init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait));
+ init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait));
+ ACCESS_FBINFO(crtc1.panpos) = -1;
+
+ err = initMatrox2(PMINFO b);
+ if (!err) {
+#ifndef CONFIG_FB_MATROX_MULTIHEAD
+ registered = 1;
+#endif
+ matroxfb_register_device(MINFO);
+ return 0;
+ }
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ kfree(minfo);
+#endif
+ return -1;
+}
+
+static void pci_remove_matrox(struct pci_dev* pdev) {
+ struct matrox_fb_info* minfo;
+
+ minfo = pci_get_drvdata(pdev);
+ matroxfb_remove(PMINFO 1);
+}
+
+static struct pci_device_id matroxfb_devices[] = {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_FB_MATROX_G
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G550,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+ {0, 0,
+ 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, matroxfb_devices);
+
+
+static struct pci_driver matroxfb_driver = {
+ .name = "matroxfb",
+ .id_table = matroxfb_devices,
+ .probe = matroxfb_probe,
+ .remove = pci_remove_matrox,
+};
+
+/* **************************** init-time only **************************** */
+
+#define RSResolution(X) ((X) & 0x0F)
+#define RS640x400 1
+#define RS640x480 2
+#define RS800x600 3
+#define RS1024x768 4
+#define RS1280x1024 5
+#define RS1600x1200 6
+#define RS768x576 7
+#define RS960x720 8
+#define RS1152x864 9
+#define RS1408x1056 10
+#define RS640x350 11
+#define RS1056x344 12 /* 132 x 43 text */
+#define RS1056x400 13 /* 132 x 50 text */
+#define RS1056x480 14 /* 132 x 60 text */
+#define RSNoxNo 15
+/* 10-FF */
+static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
+ { 640, 400, 48, 16, 39, 8, 96, 2, 70 },
+ { 640, 480, 48, 16, 33, 10, 96, 2, 60 },
+ { 800, 600, 144, 24, 28, 8, 112, 6, 60 },
+ { 1024, 768, 160, 32, 30, 4, 128, 4, 60 },
+ { 1280, 1024, 224, 32, 32, 4, 136, 4, 60 },
+ { 1600, 1200, 272, 48, 32, 5, 152, 5, 60 },
+ { 768, 576, 144, 16, 28, 6, 112, 4, 60 },
+ { 960, 720, 144, 24, 28, 8, 112, 4, 60 },
+ { 1152, 864, 192, 32, 30, 4, 128, 4, 60 },
+ { 1408, 1056, 256, 40, 32, 5, 144, 5, 60 },
+ { 640, 350, 48, 16, 39, 8, 96, 2, 70 },
+ { 1056, 344, 96, 24, 59, 44, 160, 2, 70 },
+ { 1056, 400, 96, 24, 39, 8, 160, 2, 70 },
+ { 1056, 480, 96, 24, 36, 12, 160, 3, 60 },
+ { 0, 0, ~0, ~0, ~0, ~0, 0, 0, 0 }
+};
+
+#define RSCreate(X,Y) ((X) | ((Y) << 8))
+static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
+/* default must be first */
+ { ~0, RSCreate(RSNoxNo, RS8bpp ) },
+ { 0x101, RSCreate(RS640x480, RS8bpp ) },
+ { 0x100, RSCreate(RS640x400, RS8bpp ) },
+ { 0x180, RSCreate(RS768x576, RS8bpp ) },
+ { 0x103, RSCreate(RS800x600, RS8bpp ) },
+ { 0x188, RSCreate(RS960x720, RS8bpp ) },
+ { 0x105, RSCreate(RS1024x768, RS8bpp ) },
+ { 0x190, RSCreate(RS1152x864, RS8bpp ) },
+ { 0x107, RSCreate(RS1280x1024, RS8bpp ) },
+ { 0x198, RSCreate(RS1408x1056, RS8bpp ) },
+ { 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
+ { 0x110, RSCreate(RS640x480, RS15bpp) },
+ { 0x181, RSCreate(RS768x576, RS15bpp) },
+ { 0x113, RSCreate(RS800x600, RS15bpp) },
+ { 0x189, RSCreate(RS960x720, RS15bpp) },
+ { 0x116, RSCreate(RS1024x768, RS15bpp) },
+ { 0x191, RSCreate(RS1152x864, RS15bpp) },
+ { 0x119, RSCreate(RS1280x1024, RS15bpp) },
+ { 0x199, RSCreate(RS1408x1056, RS15bpp) },
+ { 0x11D, RSCreate(RS1600x1200, RS15bpp) },
+ { 0x111, RSCreate(RS640x480, RS16bpp) },
+ { 0x182, RSCreate(RS768x576, RS16bpp) },
+ { 0x114, RSCreate(RS800x600, RS16bpp) },
+ { 0x18A, RSCreate(RS960x720, RS16bpp) },
+ { 0x117, RSCreate(RS1024x768, RS16bpp) },
+ { 0x192, RSCreate(RS1152x864, RS16bpp) },
+ { 0x11A, RSCreate(RS1280x1024, RS16bpp) },
+ { 0x19A, RSCreate(RS1408x1056, RS16bpp) },
+ { 0x11E, RSCreate(RS1600x1200, RS16bpp) },
+ { 0x1B2, RSCreate(RS640x480, RS24bpp) },
+ { 0x184, RSCreate(RS768x576, RS24bpp) },
+ { 0x1B5, RSCreate(RS800x600, RS24bpp) },
+ { 0x18C, RSCreate(RS960x720, RS24bpp) },
+ { 0x1B8, RSCreate(RS1024x768, RS24bpp) },
+ { 0x194, RSCreate(RS1152x864, RS24bpp) },
+ { 0x1BB, RSCreate(RS1280x1024, RS24bpp) },
+ { 0x19C, RSCreate(RS1408x1056, RS24bpp) },
+ { 0x1BF, RSCreate(RS1600x1200, RS24bpp) },
+ { 0x112, RSCreate(RS640x480, RS32bpp) },
+ { 0x183, RSCreate(RS768x576, RS32bpp) },
+ { 0x115, RSCreate(RS800x600, RS32bpp) },
+ { 0x18B, RSCreate(RS960x720, RS32bpp) },
+ { 0x118, RSCreate(RS1024x768, RS32bpp) },
+ { 0x193, RSCreate(RS1152x864, RS32bpp) },
+ { 0x11B, RSCreate(RS1280x1024, RS32bpp) },
+ { 0x19B, RSCreate(RS1408x1056, RS32bpp) },
+ { 0x11F, RSCreate(RS1600x1200, RS32bpp) },
+ { 0x010, RSCreate(RS640x350, RS4bpp ) },
+ { 0x012, RSCreate(RS640x480, RS4bpp ) },
+ { 0x102, RSCreate(RS800x600, RS4bpp ) },
+ { 0x104, RSCreate(RS1024x768, RS4bpp ) },
+ { 0x106, RSCreate(RS1280x1024, RS4bpp ) },
+ { 0, 0 }};
+
+static void __init matroxfb_init_params(void) {
+ /* fh from kHz to Hz */
+ if (fh < 1000)
+ fh *= 1000; /* 1kHz minimum */
+ /* maxclk */
+ if (maxclk < 1000) maxclk *= 1000; /* kHz -> Hz, MHz -> kHz */
+ if (maxclk < 1000000) maxclk *= 1000; /* kHz -> Hz, 1MHz minimum */
+ /* fix VESA number */
+ if (vesa != ~0)
+ vesa &= 0x1DFF; /* mask out clearscreen, acceleration and so on */
+
+ /* static settings */
+ for (RSptr = vesamap; RSptr->vesa; RSptr++) {
+ if (RSptr->vesa == vesa) break;
+ }
+ if (!RSptr->vesa) {
+ printk(KERN_ERR "Invalid vesa mode 0x%04X\n", vesa);
+ RSptr = vesamap;
+ }
+ {
+ int res = RSResolution(RSptr->info)-1;
+ if (left == ~0)
+ left = timmings[res].left;
+ if (!xres)
+ xres = timmings[res].xres;
+ if (right == ~0)
+ right = timmings[res].right;
+ if (!hslen)
+ hslen = timmings[res].hslen;
+ if (upper == ~0)
+ upper = timmings[res].upper;
+ if (!yres)
+ yres = timmings[res].yres;
+ if (lower == ~0)
+ lower = timmings[res].lower;
+ if (!vslen)
+ vslen = timmings[res].vslen;
+ if (!(fv||fh||maxclk||pixclock))
+ fv = timmings[res].vfreq;
+ if (depth == -1)
+ depth = RSDepth(RSptr->info);
+ }
+}
+
+static int __init matrox_init(void) {
+ int err;
+
+ matroxfb_init_params();
+ err = pci_register_driver(&matroxfb_driver);
+ dev = -1; /* accept all new devices... */
+ return err;
+}
+
+/* **************************** exit-time only **************************** */
+
+static void __exit matrox_done(void) {
+ pci_unregister_driver(&matroxfb_driver);
+}
+
+#ifndef MODULE
+
+/* ************************* init in-kernel code ************************** */
+
+static int __init matroxfb_setup(char *options) {
+ char *this_opt;
+
+ DBG(__FUNCTION__)
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt) continue;
+
+ dprintk("matroxfb_setup: option %s\n", this_opt);
+
+ if (!strncmp(this_opt, "dev:", 4))
+ dev = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "depth:", 6)) {
+ switch (simple_strtoul(this_opt+6, NULL, 0)) {
+ case 0: depth = RSText; break;
+ case 4: depth = RS4bpp; break;
+ case 8: depth = RS8bpp; break;
+ case 15:depth = RS15bpp; break;
+ case 16:depth = RS16bpp; break;
+ case 24:depth = RS24bpp; break;
+ case 32:depth = RS32bpp; break;
+ default:
+ printk(KERN_ERR "matroxfb: unsupported color depth\n");
+ }
+ } else if (!strncmp(this_opt, "xres:", 5))
+ xres = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "yres:", 5))
+ yres = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "vslen:", 6))
+ vslen = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "hslen:", 6))
+ hslen = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "left:", 5))
+ left = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "right:", 6))
+ right = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "upper:", 6))
+ upper = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "lower:", 6))
+ lower = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "pixclock:", 9))
+ pixclock = simple_strtoul(this_opt+9, NULL, 0);
+ else if (!strncmp(this_opt, "sync:", 5))
+ sync = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "vesa:", 5))
+ vesa = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "maxclk:", 7))
+ maxclk = simple_strtoul(this_opt+7, NULL, 0);
+ else if (!strncmp(this_opt, "fh:", 3))
+ fh = simple_strtoul(this_opt+3, NULL, 0);
+ else if (!strncmp(this_opt, "fv:", 3))
+ fv = simple_strtoul(this_opt+3, NULL, 0);
+ else if (!strncmp(this_opt, "mem:", 4))
+ mem = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "mode:", 5))
+ strlcpy(videomode, this_opt+5, sizeof(videomode));
+ else if (!strncmp(this_opt, "outputs:", 8))
+ strlcpy(outputs, this_opt+8, sizeof(outputs));
+ else if (!strncmp(this_opt, "dfp:", 4)) {
+ dfp_type = simple_strtoul(this_opt+4, NULL, 0);
+ dfp = 1;
+ }
+#ifdef CONFIG_PPC_PMAC
+ else if (!strncmp(this_opt, "vmode:", 6)) {
+ unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX)
+ default_vmode = vmode;
+ } else if (!strncmp(this_opt, "cmode:", 6)) {
+ unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+ switch (cmode) {
+ case 0:
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ case 24:
+ case 32:
+ default_cmode = CMODE_32;
+ break;
+ }
+ }
+#endif
+ else if (!strcmp(this_opt, "disabled")) /* nodisabled does not exist */
+ disabled = 1;
+ else if (!strcmp(this_opt, "enabled")) /* noenabled does not exist */
+ disabled = 0;
+ else if (!strcmp(this_opt, "sgram")) /* nosgram == sdram */
+ sgram = 1;
+ else if (!strcmp(this_opt, "sdram"))
+ sgram = 0;
+ else if (!strncmp(this_opt, "memtype:", 8))
+ memtype = simple_strtoul(this_opt+8, NULL, 0);
+ else {
+ int value = 1;
+
+ if (!strncmp(this_opt, "no", 2)) {
+ value = 0;
+ this_opt += 2;
+ }
+ if (! strcmp(this_opt, "inverse"))
+ inverse = value;
+ else if (!strcmp(this_opt, "accel"))
+ noaccel = !value;
+ else if (!strcmp(this_opt, "pan"))
+ nopan = !value;
+ else if (!strcmp(this_opt, "pciretry"))
+ no_pci_retry = !value;
+ else if (!strcmp(this_opt, "vga"))
+ novga = !value;
+ else if (!strcmp(this_opt, "bios"))
+ nobios = !value;
+ else if (!strcmp(this_opt, "init"))
+ noinit = !value;
+#ifdef CONFIG_MTRR
+ else if (!strcmp(this_opt, "mtrr"))
+ mtrr = value;
+#endif
+ else if (!strcmp(this_opt, "inv24"))
+ inv24 = value;
+ else if (!strcmp(this_opt, "cross4MB"))
+ cross4MB = value;
+ else if (!strcmp(this_opt, "grayscale"))
+ grayscale = value;
+ else if (!strcmp(this_opt, "dfp"))
+ dfp = value;
+ else {
+ strlcpy(videomode, this_opt, sizeof(videomode));
+ }
+ }
+ }
+ return 0;
+}
+
+static int __initdata initialized = 0;
+
+static int __init matroxfb_init(void)
+{
+ char *option = NULL;
+ int err = 0;
+
+ DBG(__FUNCTION__)
+
+ if (fb_get_options("matroxfb", &option))
+ return -ENODEV;
+ matroxfb_setup(option);
+
+ if (disabled)
+ return -ENXIO;
+ if (!initialized) {
+ initialized = 1;
+ err = matrox_init();
+ }
+ hotplug = 1;
+ /* never return failure, user can hotplug matrox later... */
+ return err;
+}
+
+module_init(matroxfb_init);
+
+#else
+
+/* *************************** init module code **************************** */
+
+MODULE_AUTHOR("(c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450/G550");
+MODULE_LICENSE("GPL");
+
+module_param(mem, int, 0);
+MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
+module_param(disabled, int, 0);
+MODULE_PARM_DESC(disabled, "Disabled (0 or 1=disabled) (default=0)");
+module_param(noaccel, int, 0);
+MODULE_PARM_DESC(noaccel, "Do not use accelerating engine (0 or 1=disabled) (default=0)");
+module_param(nopan, int, 0);
+MODULE_PARM_DESC(nopan, "Disable pan on startup (0 or 1=disabled) (default=0)");
+module_param(no_pci_retry, int, 0);
+MODULE_PARM_DESC(no_pci_retry, "PCI retries enabled (0 or 1=disabled) (default=0)");
+module_param(novga, int, 0);
+MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
+module_param(nobios, int, 0);
+MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
+module_param(noinit, int, 0);
+MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
+module_param(memtype, int, 0);
+MODULE_PARM_DESC(memtype, "Memory type for G200/G400 (see Documentation/fb/matroxfb.txt for explanation) (default=3 for G200, 0 for G400)");
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0);
+MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
+#endif
+module_param(sgram, int, 0);
+MODULE_PARM_DESC(sgram, "Indicates that G100/G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
+module_param(inv24, int, 0);
+MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
+module_param(inverse, int, 0);
+MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)");
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+module_param(dev, int, 0);
+MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)");
+#else
+module_param(dev, int, 0);
+MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=first working)");
+#endif
+module_param(vesa, int, 0);
+MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
+module_param(xres, int, 0);
+MODULE_PARM_DESC(xres, "Horizontal resolution (px), overrides xres from vesa (default=vesa)");
+module_param(yres, int, 0);
+MODULE_PARM_DESC(yres, "Vertical resolution (scans), overrides yres from vesa (default=vesa)");
+module_param(upper, int, 0);
+MODULE_PARM_DESC(upper, "Upper blank space (scans), overrides upper from vesa (default=vesa)");
+module_param(lower, int, 0);
+MODULE_PARM_DESC(lower, "Lower blank space (scans), overrides lower from vesa (default=vesa)");
+module_param(vslen, int, 0);
+MODULE_PARM_DESC(vslen, "Vertical sync length (scans), overrides lower from vesa (default=vesa)");
+module_param(left, int, 0);
+MODULE_PARM_DESC(left, "Left blank space (px), overrides left from vesa (default=vesa)");
+module_param(right, int, 0);
+MODULE_PARM_DESC(right, "Right blank space (px), overrides right from vesa (default=vesa)");
+module_param(hslen, int, 0);
+MODULE_PARM_DESC(hslen, "Horizontal sync length (px), overrides hslen from vesa (default=vesa)");
+module_param(pixclock, int, 0);
+MODULE_PARM_DESC(pixclock, "Pixelclock (ns), overrides pixclock from vesa (default=vesa)");
+module_param(sync, int, 0);
+MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
+module_param(depth, int, 0);
+MODULE_PARM_DESC(depth, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
+module_param(maxclk, int, 0);
+MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
+module_param(fh, int, 0);
+MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
+module_param(fv, int, 0);
+MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
+"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"\n");
+module_param(grayscale, int, 0);
+MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
+module_param(cross4MB, int, 0);
+MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
+module_param(dfp, int, 0);
+MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)");
+module_param(dfp_type, int, 0);
+MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)");
+module_param_string(outputs, outputs, sizeof(outputs), 0);
+MODULE_PARM_DESC(outputs, "Specifies which CRTC is mapped to which output (string of up to three letters, consisting of 0 (disabled), 1 (CRTC1), 2 (CRTC2)) (default=111 for Gx50, 101 for G200/G400 with DFP, and 100 for all other devices)");
+#ifdef CONFIG_PPC_PMAC
+module_param_named(vmode, default_vmode, int, 0);
+MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
+module_param_named(cmode, default_cmode, int, 0);
+MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit default)");
+#endif
+
+int __init init_module(void){
+
+ DBG(__FUNCTION__)
+
+ if (disabled)
+ return -ENXIO;
+
+ if (depth == 0)
+ depth = RSText;
+ else if (depth == 4)
+ depth = RS4bpp;
+ else if (depth == 8)
+ depth = RS8bpp;
+ else if (depth == 15)
+ depth = RS15bpp;
+ else if (depth == 16)
+ depth = RS16bpp;
+ else if (depth == 24)
+ depth = RS24bpp;
+ else if (depth == 32)
+ depth = RS32bpp;
+ else if (depth != -1) {
+ printk(KERN_ERR "matroxfb: depth %d is not supported, using default\n", depth);
+ depth = -1;
+ }
+ matrox_init();
+ /* never return failure; user can hotplug matrox later... */
+ return 0;
+}
+#endif /* MODULE */
+
+module_exit(matrox_done);
+EXPORT_SYMBOL(matroxfb_register_driver);
+EXPORT_SYMBOL(matroxfb_unregister_driver);
+EXPORT_SYMBOL(matroxfb_wait_for_sync);
+EXPORT_SYMBOL(matroxfb_enable_irq);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
--- /dev/null
+@exists@
+local idexpression x;
+statement S;
+constant C;
+@@
+
+* x = kmalloc(...)
+...
+if (x == NULL) S
+... when != x
+ when != if (...) { <+...x...+> }
+* return \(-C\|NULL\);