Release coccinelle-0.1.1
authorCoccinelle <cocci@diku.dk>
Sun, 3 Oct 2010 11:56:01 +0000 (13:56 +0200)
committerRene Rydhof Hansen <rrh@cs.aau.dk>
Sun, 3 Oct 2010 11:56:01 +0000 (13:56 +0200)
** Language:
    - support for initializer at toplevel, cf -test substruct

119 files changed:
.cvsignore [new file with mode: 0644]
.project [new file with mode: 0644]
Makefile
changes.txt
cocci.ml
commitmsg
commons/.cvsignore [new file with mode: 0644]
ctl/.cvsignore [new file with mode: 0644]
emacs/cocci.el
engine/.#asttoctl2.ml.1.138 [new file with mode: 0644]
engine/.#asttoctl2.ml.1.141 [new file with mode: 0644]
engine/.#check_exhaustive_pattern.ml.1.39 [new file with mode: 0644]
engine/.#cocci_vs_c_3.ml.1.154 [new file with mode: 0644]
engine/.#ctlcocci_integration.ml.1.111 [new file with mode: 0644]
engine/.#pattern3.ml.1.56 [new file with mode: 0644]
engine/.#pattern3.ml.1.57 [new file with mode: 0644]
engine/.#transformation3.ml.1.47 [new file with mode: 0644]
engine/.#transformation3.ml.1.48 [new file with mode: 0644]
engine/.cvsignore [new file with mode: 0644]
engine/asttoctl2.ml
engine/check_exhaustive_pattern.ml
engine/cocci_vs_c_3.ml
engine/cocci_vs_c_3.mli
engine/ctlcocci_integration.ml
engine/ctlcocci_integration.mli
engine/pattern3.ml
engine/transformation3.ml
engine/transformation3.mli
extra/.cvsignore [new file with mode: 0644]
extra/Makefile
extra/c_info.ml [deleted file]
extra/c_info.mli [deleted file]
flag_cocci.ml
globals/.cvsignore [new file with mode: 0644]
globals/config.ml
main.ml
menhirlib/.cvsignore [new file with mode: 0644]
parsing_c/.cvsignore [new file with mode: 0644]
parsing_c/unparse_cocci2.ml
parsing_cocci/.#arity.ml.1.81 [new file with mode: 0644]
parsing_cocci/.#arity.ml.1.82 [new file with mode: 0644]
parsing_cocci/.#ast0_cocci.ml.1.105 [new file with mode: 0644]
parsing_cocci/.#ast0_cocci.ml.1.106 [new file with mode: 0644]
parsing_cocci/.#ast0toast.ml.1.132 [new file with mode: 0644]
parsing_cocci/.#ast0toast.ml.1.133 [new file with mode: 0644]
parsing_cocci/.#ast_cocci.ml.1.142 [new file with mode: 0644]
parsing_cocci/.#ast_cocci.ml.1.143 [new file with mode: 0644]
parsing_cocci/.#check_meta.ml.1.79 [new file with mode: 0644]
parsing_cocci/.#check_meta.ml.1.80 [new file with mode: 0644]
parsing_cocci/.#compute_lines.ml.1.85 [new file with mode: 0644]
parsing_cocci/.#context_neg.ml.1.95 [new file with mode: 0644]
parsing_cocci/.#context_neg.ml.1.96 [new file with mode: 0644]
parsing_cocci/.#disjdistr.ml.1.20 [new file with mode: 0644]
parsing_cocci/.#index.ml.1.54 [new file with mode: 0644]
parsing_cocci/.#insert_plus.ml.1.68 [new file with mode: 0644]
parsing_cocci/.#insert_plus.ml.1.69 [new file with mode: 0644]
parsing_cocci/.#iso_pattern.ml.1.136 [new file with mode: 0644]
parsing_cocci/.#iso_pattern.ml.1.137 [new file with mode: 0644]
parsing_cocci/.#lexer_cocci.mll.1.80 [new file with mode: 0644]
parsing_cocci/.#parse_aux.ml.1.23 [new file with mode: 0644]
parsing_cocci/.#parse_cocci.ml.1.162 [new file with mode: 0644]
parsing_cocci/.#parse_cocci.ml.1.163 [new file with mode: 0644]
parsing_cocci/.#parser_cocci_menhir.mly.1.153 [new file with mode: 0644]
parsing_cocci/.#parser_cocci_menhir.mly.1.155 [new file with mode: 0644]
parsing_cocci/.#pretty_print_cocci.ml.1.127 [new file with mode: 0644]
parsing_cocci/.#pretty_print_cocci.ml.1.128 [new file with mode: 0644]
parsing_cocci/.#single_statement.ml.1.51 [new file with mode: 0644]
parsing_cocci/.#test_exps.ml.1.3 [new file with mode: 0644]
parsing_cocci/.#type_infer.ml.1.54 [new file with mode: 0644]
parsing_cocci/.#unify_ast.ml.1.70 [new file with mode: 0644]
parsing_cocci/.#unitary_ast0.ml.1.28 [new file with mode: 0644]
parsing_cocci/.#unparse_ast0.ml.1.107 [new file with mode: 0644]
parsing_cocci/.#unparse_ast0.ml.1.108 [new file with mode: 0644]
parsing_cocci/.#visitor_ast.ml.1.89 [new file with mode: 0644]
parsing_cocci/.#visitor_ast.ml.1.90 [new file with mode: 0644]
parsing_cocci/.#visitor_ast0.ml.1.79 [new file with mode: 0644]
parsing_cocci/.#visitor_ast0.ml.1.80 [new file with mode: 0644]
parsing_cocci/.cvsignore [new file with mode: 0644]
parsing_cocci/arity.ml
parsing_cocci/ast0_cocci.ml
parsing_cocci/ast0_cocci.mli
parsing_cocci/ast0toast.ml
parsing_cocci/ast_cocci.ml
parsing_cocci/ast_cocci.mli
parsing_cocci/check_meta.ml
parsing_cocci/compute_lines.ml
parsing_cocci/context_neg.ml
parsing_cocci/disjdistr.ml
parsing_cocci/index.ml
parsing_cocci/insert_plus.ml
parsing_cocci/iso_pattern.ml
parsing_cocci/lexer_cocci.mll
parsing_cocci/parse_aux.ml
parsing_cocci/parse_cocci.ml
parsing_cocci/parser_cocci_menhir.ml
parsing_cocci/parser_cocci_menhir.mli
parsing_cocci/parser_cocci_menhir.mly
parsing_cocci/pretty_print_cocci.ml
parsing_cocci/single_statement.ml
parsing_cocci/test_exps.ml
parsing_cocci/type_infer.ml
parsing_cocci/unify_ast.ml
parsing_cocci/unitary_ast0.ml
parsing_cocci/unparse_ast0.ml
parsing_cocci/visitor_ast.ml
parsing_cocci/visitor_ast0.ml
popl09/.cvsignore [new file with mode: 0644]
pycaml/.cvsignore [new file with mode: 0644]
python/.cvsignore [new file with mode: 0644]
tests/.cvsignore [new file with mode: 0644]
tests/double_assign.cocci
tests/if.c [new file with mode: 0644]
tests/if.cocci [new file with mode: 0644]
tests/if.res [new file with mode: 0644]
tests/substruct.c [new file with mode: 0644]
tests/substruct.cocci [new file with mode: 0644]
tests/substruct.res [new file with mode: 0644]
tests/testifdef.c [new file with mode: 0644]
tests/testifdef.cocci [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..da56228
--- /dev/null
@@ -0,0 +1,3 @@
+.depend
+Makefile.config
+spatch
diff --git a/.project b/.project
new file mode 100644 (file)
index 0000000..321c5c3
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?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>
index a6c7122..06b01a5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -57,8 +57,8 @@ LIBS=commons/commons.cma globals/globals.cma\
 
 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
@@ -107,6 +107,9 @@ BYTECODE_STATIC=-custom
 ##############################################################################
 # Top rules
 ##############################################################################
+eclipse: depend all
+configure:
+       ./configure
 
 all: rec $(EXEC)
 opt: rec.opt $(EXEC).opt
@@ -138,7 +141,7 @@ clean::
        rm -f dllpycaml_stubs.so
 
 
-.PHONY: tools
+.PHONY: tools all configure
 
 tools:
        $(MAKE) -C tools
@@ -250,14 +253,14 @@ srctar:
 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 ?
@@ -265,7 +268,7 @@ bytecodetar: all
        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::
index bbc8c07..0a0013d 100644 (file)
@@ -1,5 +1,9 @@
 -*- org -*-
 
+* 0.1.1
+
+** better support for initializer, cf -test substruct
+
 * 0.1
 
 ** first public release of the source code:
index 9953d1e..b55eb06 100644 (file)
--- a/cocci.ml
+++ b/cocci.ml
@@ -494,36 +494,40 @@ let rec interpret_dependencies local global = function
       (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
     
     
     
@@ -931,20 +935,15 @@ let rec apply_python_rule r cache newes e rules_that_have_matched
           !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
@@ -958,6 +957,10 @@ let rec apply_python_rule r cache newes e rules_that_have_matched
            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
@@ -967,10 +970,10 @@ let rec apply_python_rule r cache newes e rules_that_have_matched
                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 =
@@ -990,50 +993,49 @@ 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
@@ -1067,12 +1069,13 @@ and apply_cocci_rule r rules_that_have_ever_matched es ccs =
                              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;
@@ -1084,6 +1087,17 @@ and apply_cocci_rule r rules_that_have_ever_matched es ccs =
     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
@@ -1237,7 +1251,7 @@ and bigloop a b =
 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;
       
@@ -1268,11 +1282,11 @@ and process_a_ctl_a_env_a_toplevel2 r e c =
 
         (* 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
  )
    
index f4b65dd..2df494c 100644 (file)
--- a/commitmsg
+++ b/commitmsg
@@ -1,6 +1,4 @@
-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
diff --git a/commons/.cvsignore b/commons/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
diff --git a/ctl/.cvsignore b/ctl/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
index 58fc80a..f3f6d3d 100644 (file)
 
 ;;; 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" 
diff --git a/engine/.#asttoctl2.ml.1.138 b/engine/.#asttoctl2.ml.1.138
new file mode 100644 (file)
index 0000000..bf9268b
--- /dev/null
@@ -0,0 +1,2222 @@
+(*
+* 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
diff --git a/engine/.#asttoctl2.ml.1.141 b/engine/.#asttoctl2.ml.1.141
new file mode 100644 (file)
index 0000000..6f1f8f6
--- /dev/null
@@ -0,0 +1,2295 @@
+(*
+* 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
diff --git a/engine/.#check_exhaustive_pattern.ml.1.39 b/engine/.#check_exhaustive_pattern.ml.1.39
new file mode 100644 (file)
index 0000000..a716d1b
--- /dev/null
@@ -0,0 +1,183 @@
+(*
+* 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
+
+*)
diff --git a/engine/.#cocci_vs_c_3.ml.1.154 b/engine/.#cocci_vs_c_3.ml.1.154
new file mode 100644 (file)
index 0000000..fc1f4c0
--- /dev/null
@@ -0,0 +1,3419 @@
+(*
+* 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
+
diff --git a/engine/.#ctlcocci_integration.ml.1.111 b/engine/.#ctlcocci_integration.ml.1.111
new file mode 100644 (file)
index 0000000..5f736aa
--- /dev/null
@@ -0,0 +1,422 @@
+(*
+* 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)
diff --git a/engine/.#pattern3.ml.1.56 b/engine/.#pattern3.ml.1.56
new file mode 100644 (file)
index 0000000..5b04d31
--- /dev/null
@@ -0,0 +1,467 @@
+(*
+* 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)
diff --git a/engine/.#pattern3.ml.1.57 b/engine/.#pattern3.ml.1.57
new file mode 100644 (file)
index 0000000..9a7c6ce
--- /dev/null
@@ -0,0 +1,476 @@
+(*
+* 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)
diff --git a/engine/.#transformation3.ml.1.47 b/engine/.#transformation3.ml.1.47
new file mode 100644 (file)
index 0000000..5691a73
--- /dev/null
@@ -0,0 +1,526 @@
+(*
+* 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)
diff --git a/engine/.#transformation3.ml.1.48 b/engine/.#transformation3.ml.1.48
new file mode 100644 (file)
index 0000000..5ade85b
--- /dev/null
@@ -0,0 +1,528 @@
+(*
+* 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)
diff --git a/engine/.cvsignore b/engine/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
index bf9268b..fca5fcf 100644 (file)
@@ -577,7 +577,9 @@ and get_before_whencode wc =
     (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 =
@@ -678,7 +680,9 @@ and get_after_whencode a wc =
     (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 =
@@ -807,9 +811,12 @@ let rec ends_in_return stmt_list =
        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)
@@ -1223,7 +1230,7 @@ let dots_au is_strict toend label s wrapcode x seq_after y quantifier =
       (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)
@@ -1253,7 +1260,7 @@ let dots_au is_strict toend label s wrapcode x seq_after y quantifier =
   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 =
@@ -1285,7 +1292,7 @@ let rec dots_and_nests plus nest whencodes bef aft dotcode after label
     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
@@ -1302,7 +1309,13 @@ let rec dots_and_nests plus nest whencodes bef aft dotcode after label
                (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 =
@@ -1383,6 +1396,62 @@ let rec dots_and_nests plus nest whencodes bef aft dotcode after label
       (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 *)
   
@@ -1585,11 +1654,18 @@ and statement stmt after quantified minus_quantified
        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
@@ -1627,11 +1703,6 @@ and statement stmt after quantified minus_quantified
           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;
@@ -1726,7 +1797,8 @@ and statement stmt after quantified minus_quantified
          (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 =
@@ -1743,7 +1815,8 @@ and statement stmt after 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))
+       guard quantified
+       (function x -> Ast.set_fvs [] (Ast.rewrap stmt x))
 
   | Ast.Switch(header,lb,cases,rb) ->
       let rec intersect_all = function
@@ -1954,7 +2027,13 @@ and statement stmt after quantified minus_quantified
                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 =
@@ -1992,6 +2071,8 @@ and statement stmt after quantified minus_quantified
                                          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))
@@ -2005,6 +2086,8 @@ and statement stmt after quantified minus_quantified
                                       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
@@ -2121,9 +2204,9 @@ let rec cleanup c =
            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)
index a716d1b..2914b42 100644 (file)
@@ -42,6 +42,7 @@ let dumb_astcocci_rule_elem = function
  | 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 _ -> ()
index fc1f4c0..f2348f3 100644 (file)
@@ -543,6 +543,9 @@ module type PARAM =
     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 *
@@ -3041,8 +3044,6 @@ let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
         )
       )
 
-
-
   | A.Ty ty, nodeb -> 
       X.cocciTy fullType ty node >>= (fun ty node -> 
         return (
@@ -3051,6 +3052,14 @@ let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
         )
       )
 
+  | 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) -> 
index 57cbe35..514ef64 100644 (file)
@@ -133,6 +133,10 @@ module type PARAM =
       (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" *)
     (* -------------------------------------------------------------------- *)
index 5f736aa..2b6c75f 100644 (file)
@@ -400,7 +400,8 @@ 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)) =
+  (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)) = 
@@ -416,7 +417,7 @@ let (mysat2:
     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)
index 8dbeb76..593bca6 100644 (file)
@@ -19,7 +19,8 @@ val mysat :
   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
index 5b04d31..88560ee 100644 (file)
@@ -80,6 +80,7 @@ module XMATCH = struct
   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 *)
@@ -91,7 +92,7 @@ module XMATCH = struct
   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
 
@@ -223,6 +224,23 @@ module XMATCH = struct
       (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 *) 
@@ -279,7 +297,9 @@ module XMATCH = struct
       (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
@@ -300,62 +320,67 @@ module XMATCH = struct
    * 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 =
@@ -374,7 +399,7 @@ module XMATCH = struct
                    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)
@@ -393,7 +418,7 @@ module XMATCH = struct
 
   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
     )
@@ -428,7 +453,7 @@ module XMATCH = struct
              (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
@@ -446,7 +471,7 @@ end
 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 = {
@@ -454,7 +479,8 @@ let match_re_node2 dropped_isos a b binding =
       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
index 5691a73..84a3d33 100644 (file)
@@ -63,6 +63,7 @@ module XTRANS = struct
   type tin = { 
     extra: xinfo;
     binding: Lib_engine.metavars_binding;
+    binding0: Lib_engine.metavars_binding; (* inherited variable *)
   }
   type 'x tout = 'x option
 
@@ -144,6 +145,18 @@ module XTRANS = struct
     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 *) 
@@ -473,10 +486,10 @@ let transform_re_node a b tin =
   | 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);
@@ -496,7 +509,8 @@ let (transform2: string (* rule name *) -> string list (* 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
@@ -521,6 +535,6 @@ let (transform2: string (* rule name *) -> string list (* dropped_isos *) ->
 
 
 
-let transform a b c d = 
+let transform a b c d 
   Common.profile_code "Transformation3.transform" 
-    (fun () -> transform2 a b c d)
+    (fun () -> transform2 a b c d e)
index 2126bde..c380456 100644 (file)
@@ -1,5 +1,6 @@
 (* 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 *)
diff --git a/extra/.cvsignore b/extra/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
index 1442bdb..c70c5a3 100644 (file)
@@ -1,6 +1,6 @@
 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 
 
diff --git a/extra/c_info.ml b/extra/c_info.ml
deleted file mode 100644 (file)
index 9169bb5..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-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
-  )
-  )
-
diff --git a/extra/c_info.mli b/extra/c_info.mli
deleted file mode 100644 (file)
index c8e07a4..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-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
index 7c3b42c..af2b9b5 100644 (file)
@@ -40,6 +40,7 @@ let show_mcodekind_in_ctl = ref false
 (* the "underived" outputs *)
 let show_transinfo = ref true
 let show_binding_in_out = ref false
+let show_dependencies = ref false
 
 let windows = ref false
 
diff --git a/globals/.cvsignore b/globals/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
index 5169aa2..c5516d9 100644 (file)
@@ -1,4 +1,4 @@
-let version = "0.1"
+let version = "0.1.1"
 
 let path = 
   try (Sys.getenv "COCCINELLE_HOME") 
diff --git a/main.ml b/main.ml
index aaa0678..75ca33d 100644 (file)
--- a/main.ml
+++ b/main.ml
@@ -197,7 +197,7 @@ let short_options = [
     "  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";
@@ -254,6 +254,10 @@ let other_options = [
     "-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",  
diff --git a/menhirlib/.cvsignore b/menhirlib/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
diff --git a/parsing_c/.cvsignore b/parsing_c/.cvsignore
new file mode 100644 (file)
index 0000000..3f95352
--- /dev/null
@@ -0,0 +1,6 @@
+.depend
+*.cma
+lexer_c.ml
+parser_c.ml
+parser_c.mli
+parser_c.output
index 77e6a7f..7c5dd58 100644 (file)
@@ -524,6 +524,7 @@ and rule_elem arity re =
   | 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) ->
diff --git a/parsing_cocci/.#arity.ml.1.81 b/parsing_cocci/.#arity.ml.1.81
new file mode 100644 (file)
index 0000000..2248a97
--- /dev/null
@@ -0,0 +1,1054 @@
+(*
+* 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
diff --git a/parsing_cocci/.#arity.ml.1.82 b/parsing_cocci/.#arity.ml.1.82
new file mode 100644 (file)
index 0000000..cb31690
--- /dev/null
@@ -0,0 +1,1060 @@
+(*
+* 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
diff --git a/parsing_cocci/.#ast0_cocci.ml.1.105 b/parsing_cocci/.#ast0_cocci.ml.1.105
new file mode 100644 (file)
index 0000000..5175cf7
--- /dev/null
@@ -0,0 +1,641 @@
+(*
+* 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 *)
diff --git a/parsing_cocci/.#ast0_cocci.ml.1.106 b/parsing_cocci/.#ast0_cocci.ml.1.106
new file mode 100644 (file)
index 0000000..306fb6a
--- /dev/null
@@ -0,0 +1,645 @@
+(*
+* 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 *)
diff --git a/parsing_cocci/.#ast0toast.ml.1.132 b/parsing_cocci/.#ast0toast.ml.1.132
new file mode 100644 (file)
index 0000000..ccc23cc
--- /dev/null
@@ -0,0 +1,916 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#ast0toast.ml.1.133 b/parsing_cocci/.#ast0toast.ml.1.133
new file mode 100644 (file)
index 0000000..1948804
--- /dev/null
@@ -0,0 +1,927 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#ast_cocci.ml.1.142 b/parsing_cocci/.#ast_cocci.ml.1.142
new file mode 100644 (file)
index 0000000..a98a8dc
--- /dev/null
@@ -0,0 +1,668 @@
+(*
+* 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
diff --git a/parsing_cocci/.#ast_cocci.ml.1.143 b/parsing_cocci/.#ast_cocci.ml.1.143
new file mode 100644 (file)
index 0000000..bbbdd58
--- /dev/null
@@ -0,0 +1,672 @@
+(*
+* 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
diff --git a/parsing_cocci/.#check_meta.ml.1.79 b/parsing_cocci/.#check_meta.ml.1.79
new file mode 100644 (file)
index 0000000..28da910
--- /dev/null
@@ -0,0 +1,528 @@
+(*
+* 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 ""
diff --git a/parsing_cocci/.#check_meta.ml.1.80 b/parsing_cocci/.#check_meta.ml.1.80
new file mode 100644 (file)
index 0000000..b195e42
--- /dev/null
@@ -0,0 +1,532 @@
+(*
+* 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 ""
diff --git a/parsing_cocci/.#compute_lines.ml.1.85 b/parsing_cocci/.#compute_lines.ml.1.85
new file mode 100644 (file)
index 0000000..5a08d1f
--- /dev/null
@@ -0,0 +1,760 @@
+(*
+* 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
+    
diff --git a/parsing_cocci/.#context_neg.ml.1.95 b/parsing_cocci/.#context_neg.ml.1.95
new file mode 100644 (file)
index 0000000..e20fe00
--- /dev/null
@@ -0,0 +1,992 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#context_neg.ml.1.96 b/parsing_cocci/.#context_neg.ml.1.96
new file mode 100644 (file)
index 0000000..93e3293
--- /dev/null
@@ -0,0 +1,1002 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#disjdistr.ml.1.20 b/parsing_cocci/.#disjdistr.ml.1.20
new file mode 100644 (file)
index 0000000..c624418
--- /dev/null
@@ -0,0 +1,393 @@
+(*
+* 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
diff --git a/parsing_cocci/.#index.ml.1.54 b/parsing_cocci/.#index.ml.1.54
new file mode 100644 (file)
index 0000000..e4b98a2
--- /dev/null
@@ -0,0 +1,220 @@
+(*
+* 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 *)
diff --git a/parsing_cocci/.#insert_plus.ml.1.68 b/parsing_cocci/.#insert_plus.ml.1.68
new file mode 100644 (file)
index 0000000..12009c7
--- /dev/null
@@ -0,0 +1,941 @@
+(*
+* 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
diff --git a/parsing_cocci/.#insert_plus.ml.1.69 b/parsing_cocci/.#insert_plus.ml.1.69
new file mode 100644 (file)
index 0000000..7609cf8
--- /dev/null
@@ -0,0 +1,946 @@
+(*
+* 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
diff --git a/parsing_cocci/.#iso_pattern.ml.1.136 b/parsing_cocci/.#iso_pattern.ml.1.136
new file mode 100644 (file)
index 0000000..6bbf1a7
--- /dev/null
@@ -0,0 +1,2306 @@
+(*
+* 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
diff --git a/parsing_cocci/.#iso_pattern.ml.1.137 b/parsing_cocci/.#iso_pattern.ml.1.137
new file mode 100644 (file)
index 0000000..e8abab4
--- /dev/null
@@ -0,0 +1,2310 @@
+(*
+* 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
diff --git a/parsing_cocci/.#lexer_cocci.mll.1.80 b/parsing_cocci/.#lexer_cocci.mll.1.80
new file mode 100644 (file)
index 0000000..c066d1d
--- /dev/null
@@ -0,0 +1,700 @@
+(*
+* 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) }
diff --git a/parsing_cocci/.#parse_aux.ml.1.23 b/parsing_cocci/.#parse_aux.ml.1.23
new file mode 100644 (file)
index 0000000..fb1ff7d
--- /dev/null
@@ -0,0 +1,467 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#parse_cocci.ml.1.162 b/parsing_cocci/.#parse_cocci.ml.1.162
new file mode 100644 (file)
index 0000000..45938ff
--- /dev/null
@@ -0,0 +1,1512 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#parse_cocci.ml.1.163 b/parsing_cocci/.#parse_cocci.ml.1.163
new file mode 100644 (file)
index 0000000..a38afe9
--- /dev/null
@@ -0,0 +1,1530 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#parser_cocci_menhir.mly.1.153 b/parsing_cocci/.#parser_cocci_menhir.mly.1.153
new file mode 100644 (file)
index 0000000..a3be6b6
--- /dev/null
@@ -0,0 +1,1765 @@
+/*
+* 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)) }
diff --git a/parsing_cocci/.#parser_cocci_menhir.mly.1.155 b/parsing_cocci/.#parser_cocci_menhir.mly.1.155
new file mode 100644 (file)
index 0000000..3e30d2d
--- /dev/null
@@ -0,0 +1,1763 @@
+/*
+* 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)) }
diff --git a/parsing_cocci/.#pretty_print_cocci.ml.1.127 b/parsing_cocci/.#pretty_print_cocci.ml.1.127
new file mode 100644 (file)
index 0000000..308a25e
--- /dev/null
@@ -0,0 +1,855 @@
+(*
+* 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
+
diff --git a/parsing_cocci/.#pretty_print_cocci.ml.1.128 b/parsing_cocci/.#pretty_print_cocci.ml.1.128
new file mode 100644 (file)
index 0000000..5ca7b08
--- /dev/null
@@ -0,0 +1,859 @@
+(*
+* 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
+
diff --git a/parsing_cocci/.#single_statement.ml.1.51 b/parsing_cocci/.#single_statement.ml.1.51
new file mode 100644 (file)
index 0000000..d8b86c0
--- /dev/null
@@ -0,0 +1,596 @@
+(*
+* 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
diff --git a/parsing_cocci/.#test_exps.ml.1.3 b/parsing_cocci/.#test_exps.ml.1.3
new file mode 100644 (file)
index 0000000..528d7e2
--- /dev/null
@@ -0,0 +1,89 @@
+(*
+* 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
+
diff --git a/parsing_cocci/.#type_infer.ml.1.54 b/parsing_cocci/.#type_infer.ml.1.54
new file mode 100644 (file)
index 0000000..7ae9f85
--- /dev/null
@@ -0,0 +1,356 @@
+(*
+* 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
+  ()
diff --git a/parsing_cocci/.#unify_ast.ml.1.70 b/parsing_cocci/.#unify_ast.ml.1.70
new file mode 100644 (file)
index 0000000..a32476b
--- /dev/null
@@ -0,0 +1,565 @@
+(*
+* 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
diff --git a/parsing_cocci/.#unitary_ast0.ml.1.28 b/parsing_cocci/.#unitary_ast0.ml.1.28
new file mode 100644 (file)
index 0000000..1110f58
--- /dev/null
@@ -0,0 +1,284 @@
+(*
+* 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)
+*)
diff --git a/parsing_cocci/.#unparse_ast0.ml.1.107 b/parsing_cocci/.#unparse_ast0.ml.1.107
new file mode 100644 (file)
index 0000000..80ece57
--- /dev/null
@@ -0,0 +1,651 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#unparse_ast0.ml.1.108 b/parsing_cocci/.#unparse_ast0.ml.1.108
new file mode 100644 (file)
index 0000000..b76d3b9
--- /dev/null
@@ -0,0 +1,657 @@
+(*
+* 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)
diff --git a/parsing_cocci/.#visitor_ast.ml.1.89 b/parsing_cocci/.#visitor_ast.ml.1.89
new file mode 100644 (file)
index 0000000..6338874
--- /dev/null
@@ -0,0 +1,1048 @@
+(*
+* 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
+
diff --git a/parsing_cocci/.#visitor_ast.ml.1.90 b/parsing_cocci/.#visitor_ast.ml.1.90
new file mode 100644 (file)
index 0000000..6ac86e5
--- /dev/null
@@ -0,0 +1,1052 @@
+(*
+* 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
+
diff --git a/parsing_cocci/.#visitor_ast0.ml.1.79 b/parsing_cocci/.#visitor_ast0.ml.1.79
new file mode 100644 (file)
index 0000000..6a70898
--- /dev/null
@@ -0,0 +1,1028 @@
+(*
+* 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
diff --git a/parsing_cocci/.#visitor_ast0.ml.1.80 b/parsing_cocci/.#visitor_ast0.ml.1.80
new file mode 100644 (file)
index 0000000..36ab172
--- /dev/null
@@ -0,0 +1,1036 @@
+(*
+* 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
diff --git a/parsing_cocci/.cvsignore b/parsing_cocci/.cvsignore
new file mode 100644 (file)
index 0000000..ec28187
--- /dev/null
@@ -0,0 +1,6 @@
+.depend
+*.cma
+lexer_cocci.ml
+lexer_script.ml
+parser_cocci_menhir.ml
+parser_cocci_menhir.mli
index 2248a97..75b83b6 100644 (file)
@@ -831,6 +831,15 @@ and statement tgt stm =
        | 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)
@@ -875,7 +884,8 @@ and statement tgt stm =
        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))
@@ -884,7 +894,8 @@ and statement tgt stm =
       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) ->
@@ -892,7 +903,8 @@ and statement tgt stm =
       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)   ->
@@ -900,7 +912,8 @@ and statement tgt stm =
       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) ->
@@ -995,10 +1008,12 @@ and fninfo2arity fninfo =
         | 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
index 5175cf7..5d9f214 100644 (file)
@@ -306,6 +306,7 @@ and base_statement =
   | 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 *
@@ -337,6 +338,8 @@ 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
 
@@ -397,6 +400,8 @@ and anything =
   | 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
index 1b448fa..b77ca37 100644 (file)
@@ -279,6 +279,7 @@ and base_statement =
   | 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 *
@@ -310,6 +311,8 @@ and ('a,'b) whencode =
     WhenNot of 'a
   | WhenAlways of 'b
   | WhenModifier of Ast_cocci.when_modifier
+  | WhenNotTrue of expression
+  | WhenNotFalse of expression
 
 and statement = base_statement wrap
 
@@ -373,6 +376,8 @@ and anything =
   | 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
index ccc23cc..b04f31d 100644 (file)
@@ -683,6 +683,8 @@ and statement s =
          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,_,_) ->
@@ -770,6 +772,15 @@ and statement s =
       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
       [] -> []
@@ -884,6 +895,8 @@ and anything = 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"
 
 (* --------------------------------------------------------------------- *)
index a98a8dc..ef3d17f 100644 (file)
@@ -408,6 +408,7 @@ and base_rule_elem =
   | 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*)
@@ -462,6 +463,8 @@ 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
@@ -600,7 +603,9 @@ let get_wcfvs (whencode : ('a wrap, 'b wrap) whencode list) =
        (function
           WhenNot(a) -> get_fvs a
         | WhenAlways(a) -> get_fvs a
-        | WhenModifier(_) -> [])
+        | WhenModifier(_) -> []
+        | WhenNotTrue(e) -> get_fvs e
+        | WhenNotFalse(e) -> get_fvs e)
        whencode)
 
 (* --------------------------------------------------------------------- *)
index 0e5d0da..32fc4ca 100644 (file)
@@ -374,6 +374,7 @@ and base_rule_elem =
   | 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*)
@@ -428,6 +429,8 @@ and ('a,'b) whencode =
     WhenNot of 'a
   | WhenAlways of 'b
   | WhenModifier of when_modifier
+  | WhenNotTrue of rule_elem
+  | WhenNotFalse of rule_elem
 
 and when_modifier =
     WhenAny
index 28da910..e555f85 100644 (file)
@@ -334,17 +334,20 @@ and statement old_metas table minus s =
   | 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;
@@ -363,10 +366,12 @@ and fninfo old_metas table minus = function
   | 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
index 5a08d1f..526d75e 100644 (file)
@@ -633,6 +633,9 @@ let rec statement s =
     | 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
index e20fe00..abc2054 100644 (file)
@@ -54,6 +54,8 @@ let set_mcodekind x 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 =
@@ -76,6 +78,8 @@ 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
@@ -97,6 +101,8 @@ 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"
 
 (* --------------------------------------------------------------------- *)
@@ -638,6 +644,7 @@ let rec equal_statement s1 s2 =
   | (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
@@ -692,7 +699,9 @@ let root_equal e1 e2 =
   | (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
 
@@ -758,7 +767,9 @@ let contextify_whencode =
   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;
index c624418..bf5448a 100644 (file)
@@ -271,6 +271,7 @@ let orify_rule_elem 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 orify_rule_elem_ini = generic_orify_rule_elem disjini
 
 let disj_rule_elem r k re =
   match Ast.unwrap re with      
@@ -323,6 +324,9 @@ let disj_rule_elem r k re =
       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
index e4b98a2..3396bd9 100644 (file)
@@ -21,7 +21,7 @@
 
 
 (* 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 *)
@@ -195,6 +195,7 @@ let statement s =
   | 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]
index 12009c7..795d46c 100644 (file)
@@ -137,6 +137,8 @@ let create_root_token_table minus =
          | 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)
@@ -359,6 +361,8 @@ let call_collect_minus context_nodes :
          (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
 
@@ -465,6 +469,7 @@ let collect_plus_nodes root =
       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
 
@@ -551,6 +556,8 @@ let call_collect_plus context_nodes :
          (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
 
@@ -674,8 +681,6 @@ let insert thing thinginfo into intoinfo =
   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}
@@ -705,6 +710,7 @@ let insert thing thinginfo into intoinfo =
       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
 
index 6bbf1a7..f7975b8 100644 (file)
@@ -100,6 +100,10 @@ let anything_equal = function
   | (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
@@ -1020,6 +1024,7 @@ let match_maker checks_needed context_required whencode_allowed =
          | (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))
@@ -1041,6 +1046,14 @@ let match_maker checks_needed context_required whencode_allowed =
                             | 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
@@ -1663,6 +1676,15 @@ let instantiate bindings mv_bindings =
        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
@@ -1679,37 +1701,19 @@ let instantiate bindings mv_bindings =
        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
 
@@ -2276,7 +2280,8 @@ let rewrap_anything = function
   | 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)
 
 (* --------------------------------------------------------------------- *)
index c066d1d..46d2768 100644 (file)
@@ -219,6 +219,7 @@ let id_tokens lexbuf =
   | "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
index fb1ff7d..274b37f 100644 (file)
@@ -459,9 +459,6 @@ let make_cocci_rule_name_result nm d i a e ee =
       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)
index 45938ff..b661baf 100644 (file)
@@ -194,8 +194,11 @@ let token2c (tok,_) =
   | 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)
@@ -231,6 +234,7 @@ let token2c (tok,_) =
   | 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)
 
@@ -302,13 +306,15 @@ let plus_attachable (tok,_) =
   | 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)
 
@@ -361,13 +367,15 @@ let get_clt (tok,_) =
   | 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)
 
@@ -469,6 +477,8 @@ let update_clt (tok,x) 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)
@@ -501,6 +511,7 @@ let update_clt (tok,x) clt =
   | 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)
 
@@ -605,11 +616,12 @@ let split_token ((tok,_) as t) =
   | 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 *)
@@ -635,7 +647,7 @@ let split_token ((tok,_) as t) =
   | 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
@@ -728,7 +740,8 @@ let detect_types in_meta_decls l =
       (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
@@ -841,7 +854,8 @@ let token2line (tok,_) =
   | 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) 
@@ -853,6 +867,7 @@ let token2line (tok,_) =
   | PC.TCPar0(clt) 
 
   | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOCro(clt) | PC.TCCro(clt) 
+  | PC.TOInit(clt)
 
   | PC.TPtrOp(clt) 
 
@@ -897,6 +912,43 @@ and find_line_end inwhen line clt q = function
   | 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
@@ -1068,8 +1120,10 @@ let parse_one str parsefn file toks =
   | 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
     [] -> []
index 58c840f..e798752 100644 (file)
@@ -136,278 +136,294 @@ type token =
        (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
@@ -422,57 +438,57 @@ type token =
   | 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
@@ -482,150 +498,150 @@ type token =
   | 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
 
@@ -644,276 +660,284 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     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
@@ -1174,6 +1198,8 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           Obj.repr _v
       | TOEllipsis _v ->
           Obj.repr _v
+      | TOInit _v ->
+          Obj.repr _v
       | TOPar _v ->
           Obj.repr _v
       | TOPar0 _v ->
@@ -1220,6 +1246,8 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           Obj.repr ()
       | TRuleName _v ->
           Obj.repr _v
+      | TScript ->
+          Obj.repr ()
       | TScriptData _v ->
           Obj.repr _v
       | TShOp _v ->
@@ -1246,6 +1274,10 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           Obj.repr ()
       | TWhen _v ->
           Obj.repr _v
+      | TWhenFalse _v ->
+          Obj.repr _v
+      | TWhenTrue _v ->
+          Obj.repr _v
       | TWhile _v ->
           Obj.repr _v
       | TWhy _v ->
@@ -1300,19 +1332,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           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 =
     [|
@@ -1459,9 +1491,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1482,12 +1514,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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 =
@@ -1495,7 +1527,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          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;
@@ -1517,9 +1549,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1539,9 +1571,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1561,9 +1593,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1583,9 +1615,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1605,9 +1637,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1631,7 +1663,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1663,7 +1695,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1671,7 +1703,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1703,7 +1735,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1711,7 +1743,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1743,7 +1775,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1751,7 +1783,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1783,7 +1815,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1791,7 +1823,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1823,7 +1855,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1831,7 +1863,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1863,7 +1895,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1871,7 +1903,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1903,7 +1935,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1911,7 +1943,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1943,7 +1975,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1951,7 +1983,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -1983,7 +2015,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -1991,7 +2023,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2023,7 +2055,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2031,7 +2063,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2063,7 +2095,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2071,7 +2103,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2103,7 +2135,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2111,7 +2143,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2143,7 +2175,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2151,7 +2183,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2175,7 +2207,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2207,7 +2239,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2215,7 +2247,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2247,7 +2279,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2255,7 +2287,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2287,7 +2319,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2295,7 +2327,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2327,7 +2359,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2335,7 +2367,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2367,7 +2399,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2375,7 +2407,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2407,7 +2439,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2415,7 +2447,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2447,7 +2479,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2455,7 +2487,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2487,7 +2519,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2495,7 +2527,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2527,7 +2559,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2535,7 +2567,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2567,7 +2599,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2575,7 +2607,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2607,7 +2639,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2615,7 +2647,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2647,7 +2679,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2655,7 +2687,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2687,7 +2719,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2695,7 +2727,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2719,7 +2751,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2751,7 +2783,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2759,7 +2791,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2791,7 +2823,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2799,7 +2831,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2831,7 +2863,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2839,7 +2871,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2871,7 +2903,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2879,7 +2911,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2911,7 +2943,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2919,7 +2951,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2951,7 +2983,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2959,7 +2991,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -2991,7 +3023,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -2999,7 +3031,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3031,7 +3063,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3039,7 +3071,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3071,7 +3103,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3079,7 +3111,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3111,7 +3143,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3119,7 +3151,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3151,7 +3183,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3159,7 +3191,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3191,7 +3223,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3199,7 +3231,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3231,7 +3263,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3239,7 +3271,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3263,7 +3295,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3295,7 +3327,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3303,7 +3335,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3335,7 +3367,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3343,7 +3375,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3375,7 +3407,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3383,7 +3415,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3415,7 +3447,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3423,7 +3455,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3455,7 +3487,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3463,7 +3495,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3495,7 +3527,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3503,7 +3535,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3535,7 +3567,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3543,7 +3575,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3575,7 +3607,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3583,7 +3615,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3615,7 +3647,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3623,7 +3655,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3655,7 +3687,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3663,7 +3695,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3695,7 +3727,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3703,7 +3735,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3735,7 +3767,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3743,7 +3775,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3775,7 +3807,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3783,7 +3815,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3805,7 +3837,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3827,7 +3859,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3849,7 +3881,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3866,7 +3898,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3897,20 +3929,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3934,7 +3966,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -3966,7 +3998,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -3976,7 +4008,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4008,7 +4040,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4018,7 +4050,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4042,7 +4074,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4074,7 +4106,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4084,7 +4116,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4116,7 +4148,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4126,7 +4158,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4150,7 +4182,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4182,7 +4214,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4192,7 +4224,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4224,7 +4256,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4234,7 +4266,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4258,7 +4290,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4290,7 +4322,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4300,7 +4332,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4332,7 +4364,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4342,7 +4374,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -4366,7 +4398,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4390,7 +4422,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4414,7 +4446,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4446,19 +4478,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4495,20 +4527,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4532,7 +4564,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4569,13 +4601,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4583,7 +4615,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -4607,7 +4639,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4644,13 +4676,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4658,7 +4690,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -4682,7 +4714,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4719,13 +4751,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4733,7 +4765,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -4757,7 +4789,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4794,13 +4826,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4808,7 +4840,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -4836,7 +4868,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -4862,12 +4894,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4876,7 +4908,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -4903,7 +4935,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4911,7 +4943,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -4937,12 +4969,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4951,7 +4983,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -4978,7 +5010,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -4986,7 +5018,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -5003,7 +5035,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5033,7 +5065,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5065,7 +5097,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -5074,7 +5106,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -5091,7 +5123,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5123,7 +5155,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -5132,7 +5164,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -5154,9 +5186,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5178,9 +5210,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5202,9 +5234,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5226,9 +5258,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5250,9 +5282,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5274,9 +5306,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5298,9 +5330,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5322,9 +5354,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5346,9 +5378,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5370,9 +5402,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5394,9 +5426,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5418,9 +5450,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5444,7 +5476,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5486,13 +5518,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -5501,7 +5533,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -5525,7 +5557,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5567,13 +5599,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -5582,7 +5614,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -5606,7 +5638,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5648,13 +5680,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -5663,7 +5695,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -5684,14 +5716,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5712,14 +5744,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5736,7 +5768,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5766,7 +5798,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5790,7 +5822,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -5821,13 +5853,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -5865,13 +5897,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -5898,7 +5930,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -5906,7 +5938,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 5910 "parser_cocci_menhir.ml"
+# 5942 "parser_cocci_menhir.ml"
           
         in
         
@@ -5914,7 +5946,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          ( 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;
@@ -5946,7 +5978,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -5956,7 +5988,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 5960 "parser_cocci_menhir.ml"
+# 5992 "parser_cocci_menhir.ml"
           
         in
         
@@ -5964,7 +5996,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          ( 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;
@@ -5995,13 +6027,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6010,7 +6042,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -6031,14 +6063,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6059,14 +6091,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6103,7 +6135,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                 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;
@@ -6133,7 +6165,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6189,29 +6221,29 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6224,7 +6256,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -6245,7 +6277,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6253,7 +6285,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -6274,7 +6306,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6282,7 +6314,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -6303,14 +6335,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6331,7 +6363,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6339,7 +6371,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -6367,7 +6399,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      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;
@@ -6395,7 +6427,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      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;
@@ -6419,7 +6451,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6451,7 +6483,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6459,7 +6491,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6486,7 +6518,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6494,7 +6526,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -6518,7 +6550,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6550,7 +6582,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6558,7 +6590,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6585,7 +6617,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6593,7 +6625,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -6614,7 +6646,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6622,7 +6654,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -6650,7 +6682,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            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;
@@ -6674,7 +6706,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6705,13 +6737,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6726,7 +6758,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -6747,7 +6779,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6755,7 +6787,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -6783,7 +6815,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            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;
@@ -6807,7 +6839,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6838,13 +6870,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6858,7 +6890,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            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;
@@ -6884,7 +6916,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6892,7 +6924,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -6923,7 +6955,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6933,7 +6965,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 6937 "parser_cocci_menhir.ml"
+# 6969 "parser_cocci_menhir.ml"
           
         in
         
@@ -6942,7 +6974,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          (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;
@@ -6978,7 +7010,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -6990,7 +7022,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 6994 "parser_cocci_menhir.ml"
+# 7026 "parser_cocci_menhir.ml"
           
         in
         
@@ -6999,7 +7031,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          (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;
@@ -7023,7 +7055,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -7064,13 +7096,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7080,14 +7112,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -7133,13 +7165,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7151,14 +7183,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -7189,7 +7221,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7199,14 +7231,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -7217,7 +7249,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
              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;
@@ -7253,7 +7285,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7265,14 +7297,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -7283,7 +7315,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
              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;
@@ -7319,7 +7351,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7330,7 +7362,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 7334 "parser_cocci_menhir.ml"
+# 7366 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -7338,7 +7370,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 7342 "parser_cocci_menhir.ml"
+# 7374 "parser_cocci_menhir.ml"
           
         in
         
@@ -7349,7 +7381,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
              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;
@@ -7390,7 +7422,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7403,7 +7435,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 7407 "parser_cocci_menhir.ml"
+# 7439 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -7411,7 +7443,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 7415 "parser_cocci_menhir.ml"
+# 7447 "parser_cocci_menhir.ml"
           
         in
         
@@ -7422,7 +7454,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
              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;
@@ -7463,13 +7495,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7479,14 +7511,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -7496,7 +7528,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -7542,13 +7574,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7560,14 +7592,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -7577,7 +7609,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -7623,13 +7655,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7640,7 +7672,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 7644 "parser_cocci_menhir.ml"
+# 7676 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -7648,7 +7680,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 7652 "parser_cocci_menhir.ml"
+# 7684 "parser_cocci_menhir.ml"
           
         in
         
@@ -7658,7 +7690,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -7709,13 +7741,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7728,7 +7760,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 7732 "parser_cocci_menhir.ml"
+# 7764 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -7736,7 +7768,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 7740 "parser_cocci_menhir.ml"
+# 7772 "parser_cocci_menhir.ml"
           
         in
         
@@ -7746,7 +7778,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -7807,34 +7839,34 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7843,7 +7875,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 7847 "parser_cocci_menhir.ml"
+# 7879 "parser_cocci_menhir.ml"
           
         in
         
@@ -7855,7 +7887,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -7921,34 +7953,34 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -7959,7 +7991,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 7963 "parser_cocci_menhir.ml"
+# 7995 "parser_cocci_menhir.ml"
           
         in
         
@@ -7971,7 +8003,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -8012,18 +8044,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8032,7 +8064,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -8103,40 +8135,40 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8145,7 +8177,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 8149 "parser_cocci_menhir.ml"
+# 8181 "parser_cocci_menhir.ml"
           
         in
         
@@ -8157,7 +8189,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -8233,40 +8265,40 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8277,7 +8309,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 8281 "parser_cocci_menhir.ml"
+# 8313 "parser_cocci_menhir.ml"
           
         in
         
@@ -8289,7 +8321,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -8325,14 +8357,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8340,7 +8372,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -8368,7 +8400,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      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;
@@ -8392,7 +8424,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8409,7 +8441,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8433,7 +8465,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8465,7 +8497,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8474,7 +8506,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -8501,7 +8533,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8509,7 +8541,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -8530,7 +8562,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8552,7 +8584,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                       "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;
@@ -8583,13 +8615,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8613,7 +8645,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                    (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;
@@ -8637,7 +8669,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8671,7 +8703,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8705,7 +8737,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8722,7 +8754,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8754,7 +8786,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8778,7 +8810,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8806,7 +8838,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8827,14 +8859,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8858,7 +8890,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -8884,12 +8916,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8897,7 +8929,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -8924,7 +8956,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -8933,7 +8965,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -8954,14 +8986,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9000,14 +9032,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9028,14 +9060,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9074,14 +9106,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9102,14 +9134,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9148,14 +9180,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9179,7 +9211,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9201,7 +9233,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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 =
@@ -9212,7 +9244,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -9234,9 +9266,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9251,9 +9283,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9275,9 +9307,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9309,15 +9341,15 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9361,7 +9393,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9383,7 +9415,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9405,7 +9437,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9431,7 +9463,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9448,7 +9480,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9472,7 +9504,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9496,7 +9528,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9513,7 +9545,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9538,14 +9570,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9571,12 +9603,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -9585,7 +9617,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( [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;
@@ -9615,7 +9647,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9642,7 +9674,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -9651,7 +9683,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          ( 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;
@@ -9668,7 +9700,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9702,7 +9734,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          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;
@@ -9732,7 +9764,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9759,7 +9791,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -9769,7 +9801,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -9796,7 +9828,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -9806,7 +9838,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -9823,7 +9855,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9857,7 +9889,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          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;
@@ -9884,7 +9916,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -9894,7 +9926,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -9921,7 +9953,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -9931,7 +9963,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -9946,9 +9978,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -9974,9 +10006,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10004,9 +10036,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10034,9 +10066,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10051,9 +10083,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10079,9 +10111,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10109,9 +10141,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10139,9 +10171,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10169,9 +10201,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10186,9 +10218,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10216,9 +10248,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10233,9 +10265,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10263,9 +10295,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10293,9 +10325,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10317,9 +10349,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10343,7 +10375,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10364,7 +10396,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10372,7 +10404,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -10393,7 +10425,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10401,7 +10433,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -10422,7 +10454,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10431,7 +10463,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
   ( 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;
@@ -10491,24 +10523,24 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10522,7 +10554,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                               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;
@@ -10568,18 +10600,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10589,7 +10621,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 10593 "parser_cocci_menhir.ml"
+# 10625 "parser_cocci_menhir.ml"
           
         in
         
@@ -10601,7 +10633,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                (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;
@@ -10652,18 +10684,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10675,7 +10707,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 10679 "parser_cocci_menhir.ml"
+# 10711 "parser_cocci_menhir.ml"
           
         in
         
@@ -10687,7 +10719,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                (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;
@@ -10733,24 +10765,24 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10758,7 +10790,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 10762 "parser_cocci_menhir.ml"
+# 10794 "parser_cocci_menhir.ml"
           
         in
         
@@ -10771,7 +10803,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
              (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;
@@ -10822,24 +10854,24 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10849,7 +10881,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 10853 "parser_cocci_menhir.ml"
+# 10885 "parser_cocci_menhir.ml"
           
         in
         
@@ -10862,7 +10894,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
              (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;
@@ -10886,7 +10918,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -10907,7 +10939,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10915,13 +10947,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -10947,7 +10979,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10957,13 +10989,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -10984,7 +11016,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -10992,13 +11024,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -11024,7 +11056,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11034,13 +11066,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -11061,7 +11093,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11069,13 +11101,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -11101,7 +11133,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11111,13 +11143,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -11138,14 +11170,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11166,14 +11198,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11194,7 +11226,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11202,13 +11234,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -11234,7 +11266,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11244,13 +11276,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -11280,7 +11312,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11316,13 +11348,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11331,7 +11363,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 11335 "parser_cocci_menhir.ml"
+# 11367 "parser_cocci_menhir.ml"
           
         in
         
@@ -11341,7 +11373,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            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;
@@ -11382,13 +11414,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11399,7 +11431,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 11403 "parser_cocci_menhir.ml"
+# 11435 "parser_cocci_menhir.ml"
           
         in
         
@@ -11409,7 +11441,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            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;
@@ -11445,18 +11477,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11467,7 +11499,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           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;
@@ -11497,12 +11529,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11514,7 +11546,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11535,14 +11567,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11563,7 +11595,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11571,7 +11603,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -11595,7 +11627,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11616,7 +11648,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11624,7 +11656,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -11648,7 +11680,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11669,7 +11701,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11677,7 +11709,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -11702,14 +11734,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11734,14 +11766,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11769,11 +11801,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11801,11 +11833,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -11826,7 +11858,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11841,7 +11873,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                            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;
@@ -11862,7 +11894,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -11877,7 +11909,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                            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;
@@ -11912,7 +11944,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -11954,7 +11986,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            | _ -> 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;
@@ -11978,7 +12010,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12009,20 +12041,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12048,12 +12080,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -12062,7 +12094,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -12086,7 +12118,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12117,20 +12149,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12156,12 +12188,12 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -12170,7 +12202,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -12207,20 +12239,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12252,7 +12284,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -12260,7 +12292,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12302,18 +12334,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -12321,7 +12353,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -12373,24 +12405,24 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -12398,7 +12430,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -12422,7 +12454,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12448,7 +12480,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -12456,7 +12488,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12488,7 +12520,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -12496,7 +12528,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12527,7 +12559,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -12549,7 +12581,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12566,7 +12598,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12588,7 +12620,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12614,9 +12646,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12642,9 +12674,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12670,9 +12702,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12698,9 +12730,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12726,9 +12758,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12754,9 +12786,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12782,9 +12814,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12810,9 +12842,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12838,9 +12870,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12866,9 +12898,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12906,11 +12938,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12948,11 +12980,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -12990,11 +13022,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13032,11 +13064,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13074,11 +13106,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13116,11 +13148,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13158,9 +13190,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
       | _ ->
@@ -13175,7 +13207,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          | 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;
@@ -13199,11 +13231,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13231,11 +13263,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13256,14 +13288,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13284,7 +13316,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -13292,7 +13324,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -13309,7 +13341,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13336,14 +13368,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13360,7 +13392,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13390,7 +13422,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13407,7 +13439,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13437,7 +13469,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13454,7 +13486,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13484,7 +13516,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13501,7 +13533,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13531,7 +13563,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13548,7 +13580,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13578,7 +13610,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13595,7 +13627,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13625,7 +13657,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13642,7 +13674,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13672,7 +13704,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13689,7 +13721,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13719,7 +13751,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13736,7 +13768,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13766,7 +13798,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13783,7 +13815,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13813,7 +13845,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13830,7 +13862,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13860,7 +13892,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13877,7 +13909,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13907,7 +13939,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13924,7 +13956,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13954,7 +13986,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -13971,7 +14003,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14001,7 +14033,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14018,7 +14050,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14048,7 +14080,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14065,7 +14097,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14095,7 +14127,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14112,7 +14144,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14142,7 +14174,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14159,7 +14191,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14198,13 +14230,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -14221,7 +14253,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14251,7 +14283,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14268,7 +14300,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14292,7 +14324,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14309,7 +14341,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14333,7 +14365,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14350,7 +14382,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14374,7 +14406,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14391,7 +14423,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14415,7 +14447,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14432,7 +14464,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14456,7 +14488,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14473,7 +14505,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14497,7 +14529,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14514,7 +14546,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14538,7 +14570,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14555,7 +14587,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14579,7 +14611,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14596,7 +14628,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14620,7 +14652,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14637,7 +14669,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14661,7 +14693,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14685,7 +14717,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14725,7 +14757,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -14756,14 +14788,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14787,11 +14819,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -14842,13 +14874,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -14895,13 +14927,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -14952,13 +14984,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15009,13 +15041,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15062,13 +15094,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15115,13 +15147,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15172,13 +15204,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15226,13 +15258,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -15284,13 +15316,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -15342,13 +15374,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -15395,13 +15427,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15448,13 +15480,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15506,13 +15538,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -15559,13 +15591,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15612,13 +15644,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15665,13 +15697,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -15724,7 +15756,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
             
 # 39 "standard.mly"
     ( None )
-# 15728 "parser_cocci_menhir.ml"
+# 15760 "parser_cocci_menhir.ml"
             
           in
           
@@ -15737,13 +15769,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       | 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;
@@ -15804,7 +15836,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
             
 # 41 "standard.mly"
     ( Some x )
-# 15808 "parser_cocci_menhir.ml"
+# 15840 "parser_cocci_menhir.ml"
             
           in
           
@@ -15817,13 +15849,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       | 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;
@@ -15890,13 +15922,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       | 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;
@@ -15951,13 +15983,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -16016,13 +16048,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -16068,7 +16100,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
             
 # 39 "standard.mly"
     ( None )
-# 16072 "parser_cocci_menhir.ml"
+# 16104 "parser_cocci_menhir.ml"
             
           in
           
@@ -16076,13 +16108,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -16136,7 +16168,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
             
 # 41 "standard.mly"
     ( Some x )
-# 16140 "parser_cocci_menhir.ml"
+# 16172 "parser_cocci_menhir.ml"
             
           in
           
@@ -16144,13 +16176,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -16197,13 +16229,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( (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;
@@ -16269,13 +16301,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -16323,7 +16355,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -16390,7 +16422,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            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;
@@ -16457,7 +16489,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
            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;
@@ -16485,9 +16517,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16515,9 +16547,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16545,9 +16577,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16575,9 +16607,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16605,9 +16637,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16635,9 +16667,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16665,9 +16697,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16705,7 +16737,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -16743,7 +16775,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -16771,11 +16803,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16803,11 +16835,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16835,11 +16867,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16867,11 +16899,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16899,11 +16931,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16931,11 +16963,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16959,7 +16991,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -16983,7 +17015,31 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17005,9 +17061,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17034,14 +17090,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17068,14 +17124,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17102,14 +17158,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17136,14 +17192,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17170,14 +17226,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17204,14 +17260,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17235,7 +17291,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17259,7 +17315,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17310,28 +17366,28 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -17344,7 +17400,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -17372,9 +17428,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17400,9 +17456,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17430,9 +17486,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17447,9 +17503,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17477,9 +17533,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17494,9 +17550,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17524,9 +17580,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17554,9 +17610,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17592,14 +17648,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -17608,7 +17664,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -17644,14 +17700,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -17660,7 +17716,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
     ( 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;
@@ -17682,9 +17738,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17706,11 +17762,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17736,11 +17792,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17762,11 +17818,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17797,7 +17853,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -17818,14 +17874,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17852,14 +17908,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -17889,7 +17945,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          ( (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;
@@ -17927,7 +17983,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
   ( (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;
@@ -17957,7 +18013,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          ( (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;
@@ -17995,7 +18051,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
   ( (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;
@@ -18025,7 +18081,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          ( (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;
@@ -18066,7 +18122,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
             (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;
@@ -18101,7 +18157,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               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;
@@ -18147,7 +18203,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                   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;
@@ -18171,7 +18227,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -18192,7 +18248,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18205,7 +18261,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -18229,7 +18285,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -18250,7 +18306,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18263,7 +18319,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -18289,7 +18345,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18297,7 +18353,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -18328,7 +18384,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18338,14 +18394,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -18381,7 +18437,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18393,14 +18449,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -18424,7 +18480,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -18465,13 +18521,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18481,14 +18537,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -18534,13 +18590,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18552,14 +18608,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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;
@@ -18590,7 +18646,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18600,14 +18656,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -18615,7 +18671,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -18651,7 +18707,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18663,14 +18719,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -18678,7 +18734,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -18714,7 +18770,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18725,7 +18781,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 18729 "parser_cocci_menhir.ml"
+# 18785 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -18733,7 +18789,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 18737 "parser_cocci_menhir.ml"
+# 18793 "parser_cocci_menhir.ml"
           
         in
         
@@ -18741,7 +18797,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -18782,7 +18838,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18795,7 +18851,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 18799 "parser_cocci_menhir.ml"
+# 18855 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -18803,7 +18859,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 18807 "parser_cocci_menhir.ml"
+# 18863 "parser_cocci_menhir.ml"
           
         in
         
@@ -18811,7 +18867,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -18852,13 +18908,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18868,14 +18924,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -18885,7 +18941,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -18931,13 +18987,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -18949,14 +19005,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 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
         
@@ -18966,7 +19022,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -19012,13 +19068,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -19029,7 +19085,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 19033 "parser_cocci_menhir.ml"
+# 19089 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -19037,7 +19093,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 19041 "parser_cocci_menhir.ml"
+# 19097 "parser_cocci_menhir.ml"
           
         in
         
@@ -19047,7 +19103,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -19098,13 +19154,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -19117,7 +19173,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 19121 "parser_cocci_menhir.ml"
+# 19177 "parser_cocci_menhir.ml"
           
         in
         let s =
@@ -19125,7 +19181,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 19129 "parser_cocci_menhir.ml"
+# 19185 "parser_cocci_menhir.ml"
           
         in
         
@@ -19135,7 +19191,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       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;
@@ -19196,34 +19252,34 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -19232,7 +19288,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 19236 "parser_cocci_menhir.ml"
+# 19292 "parser_cocci_menhir.ml"
           
         in
         
@@ -19244,7 +19300,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -19310,34 +19366,34 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -19348,7 +19404,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 19352 "parser_cocci_menhir.ml"
+# 19408 "parser_cocci_menhir.ml"
           
         in
         
@@ -19360,7 +19416,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -19401,18 +19457,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -19421,7 +19477,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -19492,40 +19548,40 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -19534,7 +19590,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 19538 "parser_cocci_menhir.ml"
+# 19594 "parser_cocci_menhir.ml"
           
         in
         
@@ -19546,7 +19602,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -19622,40 +19678,40 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -19666,7 +19722,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 19670 "parser_cocci_menhir.ml"
+# 19726 "parser_cocci_menhir.ml"
           
         in
         
@@ -19678,7 +19734,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -19695,7 +19751,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19719,7 +19775,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19736,7 +19792,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19760,7 +19816,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19777,7 +19833,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19801,7 +19857,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19818,7 +19874,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19842,7 +19898,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19857,9 +19913,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19885,9 +19941,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19915,9 +19971,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19945,9 +20001,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19975,9 +20031,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -19992,9 +20048,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20022,9 +20078,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20039,9 +20095,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20069,9 +20125,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20099,9 +20155,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20129,9 +20185,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20167,7 +20223,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20203,7 +20259,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20231,11 +20287,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20263,11 +20319,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20295,11 +20351,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20327,11 +20383,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20359,11 +20415,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20391,11 +20447,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20417,9 +20473,33 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20447,9 +20527,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20477,9 +20557,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20507,9 +20587,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20537,9 +20617,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20560,14 +20640,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20592,14 +20672,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20624,14 +20704,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20656,14 +20736,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20695,7 +20775,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20719,7 +20799,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20755,13 +20835,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -20770,7 +20850,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -20802,7 +20882,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -20810,7 +20890,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20842,7 +20922,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -20851,7 +20931,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -20877,7 +20957,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -20885,7 +20965,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20911,7 +20991,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -20919,7 +20999,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -20955,13 +21035,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -20971,7 +21051,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -20995,7 +21075,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21031,13 +21111,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21046,7 +21126,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21078,7 +21158,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21086,7 +21166,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21118,7 +21198,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21127,7 +21207,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21153,7 +21233,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21161,7 +21241,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21187,7 +21267,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21195,7 +21275,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21231,13 +21311,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21247,7 +21327,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -21271,7 +21351,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21307,13 +21387,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21322,7 +21402,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21354,7 +21434,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21362,7 +21442,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21394,7 +21474,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21403,7 +21483,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21429,7 +21509,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21437,7 +21517,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21463,7 +21543,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21471,7 +21551,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21507,13 +21587,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21523,7 +21603,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -21547,7 +21627,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21583,13 +21663,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21598,7 +21678,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21630,7 +21710,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21638,7 +21718,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21670,7 +21750,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21679,7 +21759,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21705,7 +21785,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21713,7 +21793,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21739,7 +21819,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21747,7 +21827,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21783,13 +21863,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21799,7 +21879,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -21823,7 +21903,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -21844,7 +21924,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21852,7 +21932,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21873,7 +21953,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21881,7 +21961,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21902,7 +21982,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21910,7 +21990,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21931,7 +22011,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21939,7 +22019,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -21960,7 +22040,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21969,7 +22049,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -21990,7 +22070,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -21998,7 +22078,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22019,7 +22099,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22028,7 +22108,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22049,7 +22129,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22058,7 +22138,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22079,7 +22159,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22088,7 +22168,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22119,13 +22199,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22133,7 +22213,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22164,13 +22244,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22180,7 +22260,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -22204,7 +22284,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -22228,7 +22308,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -22249,7 +22329,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22257,7 +22337,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22278,7 +22358,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22286,7 +22366,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22307,7 +22387,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22315,7 +22395,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22336,7 +22416,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22344,7 +22424,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22365,7 +22445,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22374,7 +22454,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22395,7 +22475,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22403,7 +22483,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22424,7 +22504,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22433,7 +22513,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22454,7 +22534,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22463,7 +22543,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22484,7 +22564,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22493,7 +22573,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22524,13 +22604,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22538,7 +22618,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22569,13 +22649,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22585,7 +22665,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -22609,7 +22689,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -22633,7 +22713,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -22654,7 +22734,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22662,7 +22742,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22683,7 +22763,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22691,7 +22771,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22712,7 +22792,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22720,7 +22800,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22741,7 +22821,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22749,7 +22829,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22770,7 +22850,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22779,7 +22859,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22800,7 +22880,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22808,7 +22888,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22829,7 +22909,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22838,7 +22918,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22859,7 +22939,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22868,7 +22948,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22889,7 +22969,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22898,7 +22978,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -22929,13 +23009,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22943,7 +23023,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -22974,13 +23054,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -22990,7 +23070,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -23014,7 +23094,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23038,7 +23118,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23059,7 +23139,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23067,7 +23147,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -23088,7 +23168,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23096,7 +23176,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -23117,7 +23197,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23125,7 +23205,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -23146,7 +23226,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23154,7 +23234,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -23175,7 +23255,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23184,7 +23264,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -23205,7 +23285,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23213,7 +23293,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -23234,7 +23314,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23243,7 +23323,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -23264,7 +23344,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23273,7 +23353,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -23294,7 +23374,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23303,7 +23383,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
      ( 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;
@@ -23334,13 +23414,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23348,7 +23428,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -23379,13 +23459,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23395,7 +23475,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
        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;
@@ -23419,7 +23499,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23441,7 +23521,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23463,7 +23543,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23489,7 +23569,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23515,7 +23595,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23532,7 +23612,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23553,14 +23633,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23584,7 +23664,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23608,7 +23688,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23630,7 +23710,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23652,7 +23732,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23674,7 +23754,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23704,7 +23784,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23734,7 +23814,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23764,7 +23844,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23794,7 +23874,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23811,11 +23891,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23839,7 +23919,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23865,7 +23945,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -23873,7 +23953,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23904,20 +23984,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23943,19 +24023,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -23981,19 +24061,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24019,19 +24099,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24062,13 +24142,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -24079,7 +24159,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       (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;
@@ -24135,18 +24215,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24208,19 +24288,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24247,9 +24327,8 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
                 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;
                   };
                 };
@@ -24258,17 +24337,16 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           } = _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;
@@ -24312,7 +24390,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -24320,11 +24398,11 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24345,14 +24423,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24383,14 +24461,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24414,7 +24492,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24448,7 +24526,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24472,7 +24550,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24506,7 +24584,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24530,7 +24608,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24564,7 +24642,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24588,7 +24666,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24622,7 +24700,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24646,7 +24724,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24680,7 +24758,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24704,7 +24782,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24738,7 +24816,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24762,7 +24840,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24796,7 +24874,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24820,7 +24898,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24854,7 +24932,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24878,7 +24956,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24912,7 +24990,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24936,7 +25014,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24970,7 +25048,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -24994,7 +25072,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25028,7 +25106,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25052,7 +25130,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25086,7 +25164,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25110,7 +25188,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25141,13 +25219,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -25158,7 +25236,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
          (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;
@@ -25182,7 +25260,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25203,14 +25281,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25236,7 +25314,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -25244,7 +25322,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25286,25 +25364,25 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25356,31 +25434,31 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25442,37 +25520,37 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25514,25 +25592,25 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25583,36 +25661,36 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25654,13 +25732,13 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -25668,7 +25746,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25719,36 +25797,36 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25779,20 +25857,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25818,19 +25896,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25856,19 +25934,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25894,19 +25972,19 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25932,7 +26010,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -25940,7 +26018,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -25971,20 +26049,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26015,20 +26093,20 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26055,14 +26133,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26098,14 +26176,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -26113,7 +26191,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -26149,14 +26227,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -26164,7 +26242,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -26185,14 +26263,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26213,14 +26291,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26241,14 +26319,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26269,14 +26347,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26298,7 +26376,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26329,7 +26407,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -26339,7 +26417,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -26400,34 +26478,34 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -26441,7 +26519,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
               (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;
@@ -26472,7 +26550,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -26482,7 +26560,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 39 "standard.mly"
     ( None )
-# 26486 "parser_cocci_menhir.ml"
+# 26564 "parser_cocci_menhir.ml"
           
         in
         
@@ -26490,7 +26568,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
   ( 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;
@@ -26526,7 +26604,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -26538,7 +26616,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
           
 # 41 "standard.mly"
     ( Some x )
-# 26542 "parser_cocci_menhir.ml"
+# 26620 "parser_cocci_menhir.ml"
           
         in
         
@@ -26546,7 +26624,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
   ( 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;
@@ -26570,7 +26648,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26594,7 +26672,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26624,7 +26702,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26654,7 +26732,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26675,14 +26753,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26703,14 +26781,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26734,7 +26812,51 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26749,9 +26871,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26777,9 +26899,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26807,9 +26929,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26837,9 +26959,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26865,9 +26987,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26895,9 +27017,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26925,9 +27047,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26942,9 +27064,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26972,9 +27094,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -26989,9 +27111,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27019,9 +27141,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27049,9 +27171,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27079,9 +27201,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27109,9 +27231,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27139,9 +27261,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27169,9 +27291,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27199,9 +27321,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27229,9 +27351,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27255,7 +27377,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27276,7 +27398,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -27284,7 +27406,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -27308,7 +27430,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27335,14 +27457,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27369,14 +27491,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27406,7 +27528,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27433,7 +27555,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -27441,7 +27563,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -27468,14 +27590,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27511,18 +27633,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -27531,7 +27653,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -27555,7 +27677,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27582,14 +27704,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27616,14 +27738,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27653,7 +27775,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27680,7 +27802,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -27688,7 +27810,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -27715,14 +27837,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27758,18 +27880,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -27778,7 +27900,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -27802,7 +27924,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27829,14 +27951,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27863,14 +27985,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27900,7 +28022,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -27927,7 +28049,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -27935,7 +28057,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -27962,14 +28084,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28005,18 +28127,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -28025,7 +28147,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -28049,7 +28171,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28076,14 +28198,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28110,14 +28232,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28147,7 +28269,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28174,7 +28296,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -28182,7 +28304,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 # 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;
@@ -28209,14 +28331,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28252,18 +28374,18 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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
@@ -28272,7 +28394,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
       ( 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;
@@ -28293,14 +28415,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28321,14 +28443,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28349,14 +28471,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28377,14 +28499,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28405,14 +28527,14 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28440,9 +28562,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28470,9 +28592,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28508,7 +28630,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28532,7 +28654,7 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28566,9 +28688,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28602,9 +28724,9 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28634,9 +28756,81 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
         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;
@@ -28657,90 +28851,90 @@ module MenhirInterpreter = MenhirLib.TableInterpreter.Make (struct
 
 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 =
@@ -28748,7 +28942,7 @@ 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 =
@@ -28756,7 +28950,7 @@ 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"
     ))
 
 
index 3acc076..d0c52e8 100644 (file)
@@ -27,6 +27,8 @@ type token =
   | TWhy0
   | TWhy of (Data.clt)
   | TWhile of (Data.clt)
+  | TWhenTrue of (Data.clt)
+  | TWhenFalse of (Data.clt)
   | TWhen of (Data.clt)
   | TUsing
   | TTypedef
@@ -40,6 +42,7 @@ type token =
   | TSizeof of (Data.clt)
   | TShOp of (Ast_cocci.arithOp * Data.clt)
   | TScriptData of (string)
+  | TScript
   | TRuleName of (string)
   | TRightIso
   | TReverse
@@ -63,6 +66,7 @@ type token =
   | 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)
index a3be6b6..1e71638 100644 (file)
@@ -42,7 +42,7 @@ module P = Parse_aux
 %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
 
@@ -70,7 +70,7 @@ module P = Parse_aux
 %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
@@ -97,7 +97,7 @@ module P = Parse_aux
 %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
@@ -199,8 +199,8 @@ 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 }
+  | TScript TDotDot lang=pure_ident d=depends TArob
+      { P.make_script_rule_name_result lang d }
 
 extends:
   /* empty */                                     { () }
@@ -1513,6 +1513,7 @@ when_body_sequence.
 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 }
 
@@ -1541,12 +1542,17 @@ toplevel_after_stm:
 | 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
@@ -1698,15 +1704,13 @@ 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 }
+  | TWhenTrue TNotEq e = eexpr TLineEnd { [Ast0.WhenNotTrue e] }
+  | TWhenFalse TNotEq e = eexpr TLineEnd { [Ast0.WhenNotFalse e] }
 
 any_strict:
     TAny    { Ast.WhenAny }
index 308a25e..ede9f3f 100644 (file)
@@ -579,6 +579,7 @@ let rec rule_elem arity re =
   | 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) ->
@@ -698,6 +699,10 @@ and whencode notfn alwaysfn = function
   | 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"
index d8b86c0..847a83c 100644 (file)
@@ -242,6 +242,7 @@ and left_statement s =
   | 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
@@ -281,6 +282,7 @@ and right_statement s =
   | 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
@@ -544,6 +546,7 @@ let rec statement dots_before dots_after s =
   | 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 *)
index 528d7e2..815a8ea 100644 (file)
@@ -60,6 +60,11 @@ let set_test_poss =
        | _ -> 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
@@ -74,6 +79,10 @@ let set_test_poss =
     | 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
index 7ae9f85..1d566ea 100644 (file)
@@ -247,10 +247,12 @@ let rec propagate_types env =
     | 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
@@ -279,9 +281,10 @@ let rec propagate_types env =
            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,_,_) ->
index a32476b..a6dc6e5 100644 (file)
@@ -450,6 +450,7 @@ and unify_rule_elem re1 re2 =
   | (_,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
index 1110f58..31ad2c0 100644 (file)
@@ -77,10 +77,12 @@ let get_free checker t =
       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
@@ -123,12 +125,14 @@ let get_free checker t =
        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
   
index 80ece57..7fb2c75 100644 (file)
@@ -513,6 +513,7 @@ and statement arity s =
       | 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
@@ -556,6 +557,10 @@ and whencode notfn alwaysfn = function
   | 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
@@ -637,6 +642,8 @@ let unparse_anything x =
   | 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()
index 6338874..5a0014f 100644 (file)
@@ -359,6 +359,7 @@ let combiner bind option_default
       | 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]
@@ -456,6 +457,8 @@ let combiner bind option_default
       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 =
@@ -849,6 +852,7 @@ let rebuilder
        | 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) ->
@@ -967,6 +971,8 @@ let rebuilder
       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 =
index 6a70898..2e258a9 100644 (file)
@@ -419,6 +419,7 @@ let combiner bind option_default
       | 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))
@@ -468,6 +469,8 @@ let combiner bind option_default
       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 =
@@ -500,6 +503,8 @@ let combiner bind option_default
       | 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
 
@@ -893,6 +898,7 @@ let rebuilder = fun
        | 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)
@@ -954,7 +960,9 @@ let rebuilder = fun
   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 =
@@ -1002,6 +1010,8 @@ let rebuilder = fun
       | 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
 
diff --git a/popl09/.cvsignore b/popl09/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
diff --git a/pycaml/.cvsignore b/pycaml/.cvsignore
new file mode 100644 (file)
index 0000000..3245aa2
--- /dev/null
@@ -0,0 +1,3 @@
+._d
+pycaml.cma
+pycaml.customtop
diff --git a/python/.cvsignore b/python/.cvsignore
new file mode 100644 (file)
index 0000000..0a2d2b3
--- /dev/null
@@ -0,0 +1,2 @@
+.depend
+*.cma
diff --git a/tests/.cvsignore b/tests/.cvsignore
new file mode 100644 (file)
index 0000000..dc63c7c
--- /dev/null
@@ -0,0 +1 @@
+score_cocci_best.marshalled
index 584085d..d97ba97 100644 (file)
@@ -14,7 +14,7 @@ i =@p0 ...;
 ...
 i =@p <+... i ...+>;
 
-@@
+@x@
 identifier s.i;
 position s.p0;
 position p != r.p;
diff --git a/tests/if.c b/tests/if.c
new file mode 100644 (file)
index 0000000..b7204ae
--- /dev/null
@@ -0,0 +1,28 @@
+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);
+  }
+}
+
diff --git a/tests/if.cocci b/tests/if.cocci
new file mode 100644 (file)
index 0000000..b6bc92e
--- /dev/null
@@ -0,0 +1,21 @@
+@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);
diff --git a/tests/if.res b/tests/if.res
new file mode 100644 (file)
index 0000000..f5620ce
--- /dev/null
@@ -0,0 +1,38 @@
+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);
+  }
+}
+
diff --git a/tests/substruct.c b/tests/substruct.c
new file mode 100644 (file)
index 0000000..482fb12
--- /dev/null
@@ -0,0 +1,5 @@
+struct a { int a; } x[2] =
+{
+  { .a = 7, },
+  { .a = 17, },
+};
diff --git a/tests/substruct.cocci b/tests/substruct.cocci
new file mode 100644 (file)
index 0000000..b8b0eea
--- /dev/null
@@ -0,0 +1,9 @@
+@@
+expression E;
+@@
+
+{
+- .a = E,
++ DECLARE_A(E),
+}
+
diff --git a/tests/substruct.res b/tests/substruct.res
new file mode 100644 (file)
index 0000000..861f6b2
--- /dev/null
@@ -0,0 +1,5 @@
+struct a { int a; } x[2] =
+{
+  { DECLARE_A(7), },
+  { DECLARE_A(17), },
+};
diff --git a/tests/testifdef.c b/tests/testifdef.c
new file mode 100644 (file)
index 0000000..b25972a
--- /dev/null
@@ -0,0 +1,2601 @@
+/*
+ *
+ * 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:
+ */
+
diff --git a/tests/testifdef.cocci b/tests/testifdef.cocci
new file mode 100644 (file)
index 0000000..6abb400
--- /dev/null
@@ -0,0 +1,12 @@
+@exists@
+local idexpression x;
+statement S;
+constant C;
+@@
+
+* x = kmalloc(...)
+...
+if (x == NULL) S
+... when != x
+    when != if (...) { <+...x...+> }
+* return \(-C\|NULL\);