- Try to do better pretty printing when array elements are individually
[bpt/coccinelle.git] / parsing_cocci / ast0toast.ml
index dca8b8e..820f848 100644 (file)
@@ -1,25 +1,30 @@
 (*
-* Copyright 2005-2009, 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.
-*)
-
-
+ * Copyright 2012, INRIA
+ * Julia Lawall, Gilles Muller
+ * Copyright 2010-2011, INRIA, University of Copenhagen
+ * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
+ * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
+ * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
+ * 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.
+ *)
+
+
+# 0 "./ast0toast.ml"
 (* 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
@@ -29,7 +34,6 @@ module Ast0 = Ast0_cocci
 module Ast = Ast_cocci
 module V0 = Visitor_ast0
 module VT0 = Visitor_ast0_types
-module V = Visitor_ast
 
 let unitary = Type_cocci.Unitary
 
@@ -53,7 +57,7 @@ let inline_mcodes =
     match (Ast0.get_mcodekind e) with
       Ast0.MINUS(replacements) ->
        (match !replacements with
-         ([],_) -> ()
+         (Ast.NOREPLACEMENT,_) -> ()
        | replacements ->
            let minus_try = function
                (true,mc) ->
@@ -94,83 +98,106 @@ let inline_mcodes =
                else starter @ ender in
          (lst,
           {endinfo with Ast0.tline_start = startinfo.Ast0.tline_start}) in
-       let attach_bef bef beforeinfo = function
+       let attach_bef bef beforeinfo befit = function
            (true,mcl) ->
              List.iter
                (function
                    Ast0.MINUS(mreplacements) ->
-                     let (mrepl,tokeninfo) = !mreplacements in
-                     mreplacements := concat bef beforeinfo mrepl tokeninfo
+                     (match !mreplacements with
+                       (Ast.NOREPLACEMENT,tokeninfo) ->
+                         mreplacements :=
+                           (Ast.REPLACEMENT(bef,befit),beforeinfo)
+                     | (Ast.REPLACEMENT(anythings,it),tokeninfo) ->
+                         let (newbef,newinfo) =
+                           concat bef beforeinfo anythings tokeninfo in
+                         let it = Ast.lub_count befit it in
+                         mreplacements :=
+                           (Ast.REPLACEMENT(newbef,it),newinfo))
                  | Ast0.CONTEXT(mbefaft) ->
                      (match !mbefaft with
-                       (Ast.BEFORE(mbef),mbeforeinfo,a) ->
+                       (Ast.BEFORE(mbef,it),mbeforeinfo,a) ->
                          let (newbef,newinfo) =
                            concat bef beforeinfo mbef mbeforeinfo in
-                         mbefaft := (Ast.BEFORE(newbef),newinfo,a)
-                     | (Ast.AFTER(maft),_,a) ->
+                         let it = Ast.lub_count befit it in
+                         mbefaft := (Ast.BEFORE(newbef,it),newinfo,a)
+                     | (Ast.AFTER(maft,it),_,a) ->
+                         let it = Ast.lub_count befit it in
                          mbefaft :=
-                           (Ast.BEFOREAFTER(bef,maft),beforeinfo,a)
-                     | (Ast.BEFOREAFTER(mbef,maft),mbeforeinfo,a) ->
+                           (Ast.BEFOREAFTER(bef,maft,it),beforeinfo,a)
+                     | (Ast.BEFOREAFTER(mbef,maft,it),mbeforeinfo,a) ->
                          let (newbef,newinfo) =
                            concat bef beforeinfo mbef mbeforeinfo in
+                         let it = Ast.lub_count befit it in
                          mbefaft :=
-                           (Ast.BEFOREAFTER(newbef,maft),newinfo,a)
+                           (Ast.BEFOREAFTER(newbef,maft,it),newinfo,a)
                      | (Ast.NOTHING,_,a) ->
-                         mbefaft := (Ast.BEFORE(bef),beforeinfo,a))
+                         mbefaft :=
+                           (Ast.BEFORE(bef,befit),beforeinfo,a))
                  |     _ -> failwith "unexpected annotation")
                mcl
          | _ ->
              Printf.printf "before %s\n" (Dumper.dump bef);
              failwith
                "context tree should not have bad code before" in
-       let attach_aft aft afterinfo = function
+       let attach_aft aft afterinfo aftit = function
            (true,mcl) ->
              List.iter
                (function
                    Ast0.MINUS(mreplacements) ->
-                     let (mrepl,tokeninfo) = !mreplacements in
-                     mreplacements := concat mrepl tokeninfo aft afterinfo
+                     (match !mreplacements with
+                       (Ast.NOREPLACEMENT,tokeninfo) ->
+                         mreplacements :=
+                           (Ast.REPLACEMENT(aft,aftit),afterinfo)
+                     | (Ast.REPLACEMENT(anythings,it),tokeninfo) ->
+                         let (newaft,newinfo) =
+                           concat anythings tokeninfo aft afterinfo in
+                         let it = Ast.lub_count aftit it in
+                         mreplacements :=
+                           (Ast.REPLACEMENT(newaft,it),newinfo))
                  | Ast0.CONTEXT(mbefaft) ->
                      (match !mbefaft with
-                       (Ast.BEFORE(mbef),b,_) ->
+                       (Ast.BEFORE(mbef,it),b,_) ->
+                         let it = Ast.lub_count aftit it in
                          mbefaft :=
-                           (Ast.BEFOREAFTER(mbef,aft),b,afterinfo)
-                     | (Ast.AFTER(maft),b,mafterinfo) ->
+                           (Ast.BEFOREAFTER(mbef,aft,it),b,afterinfo)
+                     | (Ast.AFTER(maft,it),b,mafterinfo) ->
                          let (newaft,newinfo) =
                            concat maft mafterinfo aft afterinfo in
-                         mbefaft := (Ast.AFTER(newaft),b,newinfo)
-                     | (Ast.BEFOREAFTER(mbef,maft),b,mafterinfo) ->
+                         let it = Ast.lub_count aftit it in
+                         mbefaft := (Ast.AFTER(newaft,it),b,newinfo)
+                     | (Ast.BEFOREAFTER(mbef,maft,it),b,mafterinfo) ->
                          let (newaft,newinfo) =
                            concat maft mafterinfo aft afterinfo in
+                         let it = Ast.lub_count aftit it in
                          mbefaft :=
-                           (Ast.BEFOREAFTER(mbef,newaft),b,newinfo)
+                           (Ast.BEFOREAFTER(mbef,newaft,it),b,newinfo)
                      | (Ast.NOTHING,b,_) ->
-                         mbefaft := (Ast.AFTER(aft),b,afterinfo))
+                         mbefaft := (Ast.AFTER(aft,aftit),b,afterinfo))
                  |     _ -> failwith "unexpected annotation")
                mcl
          | _ ->
              failwith
                "context tree should not have bad code after" in
        (match !befaft with
-         (Ast.BEFORE(bef),beforeinfo,_) ->
-           attach_bef bef beforeinfo
+         (Ast.BEFORE(bef,it),beforeinfo,_) ->
+           attach_bef bef beforeinfo it
              (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start)
-       | (Ast.AFTER(aft),_,afterinfo) ->
-           attach_aft aft afterinfo
+       | (Ast.AFTER(aft,it),_,afterinfo) ->
+           attach_aft aft afterinfo it
              (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
-       | (Ast.BEFOREAFTER(bef,aft),beforeinfo,afterinfo) ->
-           attach_bef bef beforeinfo
+       | (Ast.BEFOREAFTER(bef,aft,it),beforeinfo,afterinfo) ->
+           attach_bef bef beforeinfo it
              (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start);
-           attach_aft aft afterinfo
+           attach_aft aft afterinfo it
              (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
        | (Ast.NOTHING,_,_) -> ())
-    | Ast0.PLUS -> () in
+    | Ast0.PLUS -> () in
   V0.flat_combiner bind option_default
     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
+    do_nothing do_nothing do_nothing do_nothing
 
 (* --------------------------------------------------------------------- *)
 (* For function declarations.  Can't use the mcode at the root, because that
@@ -183,40 +210,62 @@ let check_allminus =
   let option_default = true in
   let mcode (_,_,_,mc,_,_) =
     match mc with
-      Ast0.MINUS(r) -> let (plusses,_) = !r in plusses = []
+      Ast0.MINUS(r) -> let (plusses,_) = !r in plusses = Ast.NOREPLACEMENT
     | _ -> false in
 
-  (* special case for disj *)
+  (* special case for disj and asExpr etc *)
+  let ident r k e =
+    match Ast0.unwrap e with
+      Ast0.DisjId(starter,id_list,mids,ender) ->
+       List.for_all r.VT0.combiner_rec_ident id_list
+    | Ast0.AsIdent(id,asid) -> k id
+    | _ -> k e in
+
   let expression r k e =
     match Ast0.unwrap e with
       Ast0.DisjExpr(starter,expr_list,mids,ender) ->
        List.for_all r.VT0.combiner_rec_expression expr_list
+    | Ast0.AsExpr(exp,asexp) -> k exp
     | _ -> k e in
 
   let declaration r k e =
     match Ast0.unwrap e with
       Ast0.DisjDecl(starter,decls,mids,ender) ->
        List.for_all r.VT0.combiner_rec_declaration decls
+    | Ast0.AsDecl(decl,asdecl) -> k decl
     | _ -> k e in
 
   let typeC r k e =
     match Ast0.unwrap e with
       Ast0.DisjType(starter,decls,mids,ender) ->
        List.for_all r.VT0.combiner_rec_typeC decls
+    | Ast0.AsType(ty,asty) -> k ty
+    | _ -> k e in
+
+  let initialiser r k e =
+    match Ast0.unwrap e with
+      Ast0.AsInit(init,asinit) -> k init
     | _ -> 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.VT0.combiner_rec_statement_dots statement_dots_list
+    | Ast0.AsStmt(stmt,asstmt) -> k stmt
+    | _ -> k e in
+
+  let case_line r k e =
+    match Ast0.unwrap e with
+      Ast0.DisjCase(starter,case_lines,mids,ender) ->
+       List.for_all r.VT0.combiner_rec_case_line case_lines
     | _ -> k e in
 
   V0.flat_combiner bind option_default
     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
+    ident expression typeC initialiser donothing declaration
+    statement donothing case_line donothing
 
 (* --------------------------------------------------------------------- *)
 (* --------------------------------------------------------------------- *)
@@ -237,28 +286,50 @@ let convert_info info =
   { Ast.line = info.Ast0.pos_info.Ast0.line_start;
     Ast.column = info.Ast0.pos_info.Ast0.column;
     Ast.strbef = strings_to_s info.Ast0.strings_before;
-    Ast.straft = strings_to_s info.Ast0.strings_after;}
+    Ast.straft = strings_to_s info.Ast0.strings_after;
+  }
 
 let convert_mcodekind adj = function
     Ast0.MINUS(replacements) ->
       let (replacements,_) = !replacements in
-      Ast.MINUS(Ast.NoPos,[],adj,replacements)
-  | Ast0.PLUS -> Ast.PLUS
+      Ast.MINUS(Ast.NoPos,[],Ast.ADJ adj,replacements)
+  | Ast0.PLUS count -> Ast.PLUS count
   | Ast0.CONTEXT(befaft) ->
-      let (befaft,_,_) = !befaft in Ast.CONTEXT(Ast.NoPos,befaft)
+      let (befaft,_,_) = !befaft in
+      Ast.CONTEXT(Ast.NoPos,befaft)
   | Ast0.MIXED(_) -> failwith "not possible for mcode"
 
+let convert_fake_mcode (_,mc,adj) = convert_mcodekind adj mc
+
+let convert_allminus_mcodekind allminus = function
+    Ast0.CONTEXT(befaft) ->
+      let (befaft,_,_) = !befaft in
+      if allminus
+      then
+       (match befaft with
+         Ast.NOTHING ->
+           Ast.MINUS(Ast.NoPos,[],Ast.ALLMINUS,Ast.NOREPLACEMENT)
+       | Ast.BEFORE(a,ct) | Ast.AFTER(a,ct) ->
+           Ast.MINUS(Ast.NoPos,[],Ast.ALLMINUS,Ast.REPLACEMENT(a,ct))
+       | Ast.BEFOREAFTER(b,a,ct) ->
+           Ast.MINUS(Ast.NoPos,[],Ast.ALLMINUS,Ast.REPLACEMENT(b@a,ct)))
+      else Ast.CONTEXT(Ast.NoPos,befaft)
+  | _ -> failwith "convert_allminus_mcodekind: unexpected mcodekind"
+
 let pos_mcode(term,_,info,mcodekind,pos,adj) =
   (* avoids a recursion problem *)
-  (term,convert_info info,convert_mcodekind adj mcodekind,Ast.NoMetaPos)
+  (term,convert_info info,convert_mcodekind adj mcodekind,[])
 
 let mcode (term,_,info,mcodekind,pos,adj) =
   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 adj mcodekind,pos)
+    List.fold_left
+      (function prev ->
+       function
+           Ast0.MetaPosTag(Ast0.MetaPos(pos,constraints,per)) ->
+             (Ast.MetaPos(pos_mcode pos,constraints,per,unitary,false))::prev
+         | _ -> prev)
+      [] !pos in
+  (term,convert_info info,convert_mcodekind adj mcodekind,List.rev pos)
 
 (* --------------------------------------------------------------------- *)
 (* Dots *)
@@ -291,15 +362,16 @@ 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
+    | Ast0.DisjId(_,id_list,_,_) ->
+       Ast.DisjId(List.map ident id_list)
+    | Ast0.MetaId(name,constraints,_,_) ->
        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.AsIdent(id,asid) ->
+       Ast.AsIdent(ident id,ident asid)
     | Ast0.OptIdent(id) -> Ast.OptIdent(ident id)
     | Ast0.UniqueIdent(id) -> Ast.UniqueIdent(ident id))
 
@@ -321,6 +393,8 @@ and expression e =
        Ast.FunCall(fn,lp,args,rp)
     | Ast0.Assignment(left,op,right,simple) ->
        Ast.Assignment(expression left,mcode op,expression right,simple)
+    | Ast0.Sequence(left,op,right) ->
+       Ast.Sequence(expression left,mcode op,expression right)
     | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
        let exp1 = expression exp1 in
        let why = mcode why in
@@ -347,29 +421,35 @@ and expression e =
     | 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)
+       let allminus = check_allminus.VT0.combiner_rec_expression e in
+       Ast.Cast(mcode lp,typeC allminus 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)
+       let allminus = check_allminus.VT0.combiner_rec_expression e in
+       Ast.SizeOfType(mcode szf, mcode lp,typeC allminus ty,mcode rp)
+    | Ast0.TypeExp(ty) ->
+       let allminus = check_allminus.VT0.combiner_rec_expression e in
+       Ast.TypeExp(typeC allminus ty)
+    | Ast0.Constructor(lp,ty,rp,init) ->
+       let allminus = check_allminus.VT0.combiner_rec_expression e in
+       Ast.Constructor(mcode lp,typeC allminus ty,mcode rp,initialiser init)
+    | Ast0.MetaErr(name,cstrts,_)  ->
+         Ast.MetaErr(mcode name,constraints cstrts,unitary,false)
+    | Ast0.MetaExpr(name,cstrts,ty,form,_)  ->
+         Ast.MetaExpr(mcode name,constraints cstrts,unitary,ty,form,false)
+    | Ast0.MetaExprList(name,lenname,_) ->
+       Ast.MetaExprList(mcode name,do_lenname lenname,unitary,false)
+    | Ast0.AsExpr(expr,asexpr) ->
+       Ast.AsExpr(expression expr,expression asexpr)
     | Ast0.EComma(cm)         -> Ast.EComma(mcode cm)
     | Ast0.DisjExpr(_,exps,_,_)     ->
        Ast.DisjExpr(List.map expression exps)
-    | Ast0.NestExpr(_,exp_dots,_,whencode,multi) ->
+    | Ast0.NestExpr(starter,exp_dots,ender,whencode,multi) ->
+       let starter = mcode starter in
        let whencode = get_option expression whencode in
-       Ast.NestExpr(dots expression exp_dots,whencode,multi)
+       let ender = mcode ender in
+       Ast.NestExpr(starter,dots expression exp_dots,ender,whencode,multi)
     | Ast0.Edots(dots,whencode) ->
        let dots = mcode dots in
        let whencode = get_option expression whencode in
@@ -388,12 +468,24 @@ and expression e =
 
 and expression_dots ed = dots expression ed
 
+and constraints c =
+  match c with
+      Ast0.NoConstraint        -> Ast.NoConstraint
+    | Ast0.NotIdCstrt   idctrt -> Ast.NotIdCstrt idctrt
+    | Ast0.NotExpCstrt  exps   -> Ast.NotExpCstrt (List.map expression exps)
+    | Ast0.SubExpCstrt  ids    -> Ast.SubExpCstrt ids
+
+and do_lenname = function
+    Ast0.MetaListLen(nm) -> Ast.MetaListLen(mcode nm,unitary,false)
+  | Ast0.CstListLen n -> Ast.CstListLen n
+  | Ast0.AnyListLen -> Ast.AnyListLen
+
 (* --------------------------------------------------------------------- *)
 (* Types *)
 
 and rewrap_iso t t1 = rewrap t (do_isos (Ast0.get_iso t)) t1
 
-and typeC t =
+and typeC allminus t =
   rewrap t (do_isos (Ast0.get_iso t))
     (match Ast0.unwrap t with
       Ast0.ConstVol(cv,ty) ->
@@ -408,7 +500,8 @@ and typeC t =
          List.map
            (function ty ->
              Ast.Type
-               (Some (mcode cv),rewrap_iso ty (base_typeC ty)))
+               (allminus, Some (mcode cv),
+                rewrap_iso ty (base_typeC allminus 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
@@ -419,36 +512,44 @@ and typeC t =
     | Ast0.BaseType(_) | Ast0.Signed(_,_) | Ast0.Pointer(_,_)
     | Ast0.FunctionPointer(_,_,_,_,_,_,_) | Ast0.FunctionType(_,_,_,_)
     | Ast0.Array(_,_,_,_) | Ast0.EnumName(_,_) | 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 =
+    | Ast0.StructUnionDef(_,_,_,_) | Ast0.EnumDef(_,_,_,_)
+    | Ast0.TypeName(_) | Ast0.MetaType(_,_) ->
+       Ast.Type(allminus,None,rewrap t no_isos (base_typeC allminus t))
+    | Ast0.DisjType(_,types,_,_) ->
+       Ast.DisjType(List.map (typeC allminus) types)
+    | Ast0.AsType(ty,asty) ->
+       Ast.AsType(typeC allminus ty,typeC allminus asty)
+    | Ast0.OptType(ty) -> Ast.OptType(typeC allminus ty)
+    | Ast0.UniqueType(ty) -> Ast.UniqueType(typeC allminus ty))
+
+and base_typeC allminus t =
   match Ast0.unwrap t with
     Ast0.BaseType(ty,strings) -> Ast.BaseType(ty,List.map mcode strings)
   | Ast0.Signed(sgn,ty) ->
-      Ast.SignedT(mcode sgn,
-                 get_option (function x -> rewrap_iso x (base_typeC x)) ty)
-  | Ast0.Pointer(ty,star) -> Ast.Pointer(typeC ty,mcode star)
+      Ast.SignedT
+       (mcode sgn,
+        get_option (function x -> rewrap_iso x (base_typeC allminus x)) ty)
+  | Ast0.Pointer(ty,star) -> Ast.Pointer(typeC allminus ty,mcode star)
   | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
       Ast.FunctionPointer
-       (typeC ty,mcode lp1,mcode star,mcode rp1,
+       (typeC allminus ty,mcode lp1,mcode star,mcode rp1,
         mcode lp2,parameter_list params,mcode rp2)
   | Ast0.FunctionType(ret,lp,params,rp) ->
       let allminus = check_allminus.VT0.combiner_rec_typeC t in
       Ast.FunctionType
-       (allminus,get_option typeC ret,mcode lp,
+       (allminus,get_option (typeC allminus) 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)
+      Ast.Array(typeC allminus ty,mcode lb,get_option expression size,
+               mcode rb)
   | Ast0.EnumName(kind,name) ->
-      Ast.EnumName(mcode kind,ident name)
+      Ast.EnumName(mcode kind,get_option ident name)
+  | Ast0.EnumDef(ty,lb,ids,rb) ->
+      Ast.EnumDef(typeC allminus ty,mcode lb,dots expression ids,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,
+      Ast.StructUnionDef(typeC allminus ty,mcode lb,
                         dots declaration decls,
                         mcode rb)
   | Ast0.TypeName(name) -> Ast.TypeName(mcode name)
@@ -464,9 +565,16 @@ and base_typeC t =
 and declaration d =
   rewrap d (do_isos (Ast0.get_iso d))
     (match Ast0.unwrap d with
-      Ast0.Init(stg,ty,id,eq,ini,sem) ->
+      Ast0.MetaDecl(name,_) -> Ast.MetaDecl(mcode name,unitary,false)
+    | Ast0.MetaField(name,_) -> Ast.MetaField(mcode name,unitary,false)
+    | Ast0.MetaFieldList(name,lenname,_) ->
+       Ast.MetaFieldList(mcode name,do_lenname lenname,unitary,false)
+    | Ast0.AsDecl(decl,asdecl) ->
+       Ast.AsDecl(declaration decl,declaration asdecl)
+    | Ast0.Init(stg,ty,id,eq,ini,sem) ->
+       let allminus = check_allminus.VT0.combiner_rec_declaration d in
        let stg = get_option mcode stg in
-       let ty = typeC ty in
+       let ty = typeC allminus ty in
        let id = ident id in
        let eq = mcode eq in
        let ini = initialiser ini in
@@ -479,13 +587,17 @@ and declaration d =
            Ast.UnInit(get_option mcode stg,
                       rewrap ty (do_isos (Ast0.get_iso ty))
                         (Ast.Type
-                           (None,
+                           (allminus,None,
                             rewrap ty no_isos
                               (Ast.FunctionType
-                                 (allminus,get_option typeC tyx,mcode lp1,
+                                 (allminus,get_option (typeC allminus) tyx,
+                                  mcode lp1,
                                   parameter_list params,mcode rp1)))),
                       ident id,mcode sem)
-       | _ -> Ast.UnInit(get_option mcode stg,typeC ty,ident id,mcode sem))
+       | _ ->
+           let allminus = check_allminus.VT0.combiner_rec_declaration d in
+           Ast.UnInit(get_option mcode stg,typeC allminus ty,ident id,
+                      mcode sem))
     | Ast0.MacroDecl(name,lp,args,rp,sem) ->
        let name = ident name in
        let lp = mcode lp in
@@ -493,12 +605,24 @@ and declaration d =
        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.MacroDeclInit(name,lp,args,rp,eq,ini,sem) ->
+       let name = ident name in
+       let lp = mcode lp in
+       let args = dots expression args in
+       let rp = mcode rp in
+       let eq = mcode eq in
+       let ini = initialiser ini in
+       let sem = mcode sem in
+       Ast.MacroDeclInit(name,lp,args,rp,eq,ini,sem)
+    | Ast0.TyDecl(ty,sem) ->
+       let allminus = check_allminus.VT0.combiner_rec_declaration d in
+       Ast.TyDecl(typeC allminus ty,mcode sem)
     | Ast0.Typedef(stg,ty,id,sem) ->
-       let id = typeC id in
+       let allminus = check_allminus.VT0.combiner_rec_declaration d in
+       let id = typeC allminus id in
        (match Ast.unwrap id with
-         Ast.Type(None,id) -> (* only MetaType or Id *)
-           Ast.Typedef(mcode stg,typeC ty,id,mcode sem)
+         Ast.Type(_,None,id) -> (* only MetaType or Id *)
+           Ast.Typedef(mcode stg,typeC allminus ty,id,mcode sem)
        | _ -> failwith "bad typedef")
     | Ast0.DisjDecl(_,decls,_,_) -> Ast.DisjDecl(List.map declaration decls)
     | Ast0.Ddots(dots,whencode) ->
@@ -514,37 +638,73 @@ and declaration_dots l = dots declaration l
 (* Initialiser *)
 
 and strip_idots initlist =
+  let isminus mc =
+    match Ast0.get_mcode_mcodekind mc with
+      Ast0.MINUS _ -> true
+    | _ -> false in
   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.DOTS(l) ->
+      let l =
+       match List.rev l with
+         [] | [_] -> l
+       | x::y::xs ->
+           (match (Ast0.unwrap x,Ast0.unwrap y) with
+             (Ast0.IComma _,Ast0.Idots _) ->
+               (* drop comma that was added by add_comma *)
+               List.rev (y::xs)
+           | _ -> l) in
+      let (whencode,init,dotinfo) =
+       let rec loop = function
+           [] -> ([],[],[])
+         | x::rest ->
+             (match Ast0.unwrap x 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)
+                 let (restwhen,restinit,dotinfo) = loop rest in
+                 (whencode :: restwhen, restinit,
+                   (isminus dots)::dotinfo)
+             | Ast0.Idots(dots,None) ->
+                 let (restwhen,restinit,dotinfo) = loop rest in
+                 (restwhen, restinit, (isminus dots)::dotinfo)
+             | _ ->
+                 let (restwhen,restinit,dotinfo) = loop rest in
+                 (restwhen,x::restinit,dotinfo)) in
+       loop l in
+      let allminus =
+       if List.for_all (function x -> not x) dotinfo
+       then false (* false if no dots *)
+       else
+         if List.for_all (function x -> x) dotinfo
+         then true
+         else failwith "inconsistent annotations on initialiser list dots" in
+      (whencode, init, allminus)
   | 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.MetaInit(name,_) -> Ast.MetaInit(mcode name,unitary,false)
+    | Ast0.MetaInitList(name,lenname,_) ->
+       Ast.MetaInitList(mcode name,do_lenname lenname,unitary,false)
+    | Ast0.AsInit(init,asinit) ->
+       Ast.AsInit(initialiser init,initialiser asinit)
     | 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.InitList(lb,initlist,rb,true) ->
+       Ast.ArInitList(mcode lb,dots initialiser initlist,mcode rb)
+    | Ast0.InitList(lb,initlist,rb,false) ->
+       let (whencode,initlist,allminus) = strip_idots initlist in
+       Ast.StrInitList
+         (allminus,mcode lb,List.map initialiser initlist,mcode rb,
+          List.map initialiser whencode)
     | Ast0.InitGccExt(designators,eq,ini) ->
        Ast.InitGccExt(List.map designator designators,mcode eq,
                       initialiser ini)
     | Ast0.InitGccName(name,eq,ini) ->
        Ast.InitGccName(ident name,mcode eq,initialiser ini)
     | Ast0.IComma(comma) -> Ast.IComma(mcode comma)
-    | Ast0.Idots(_,_) -> failwith "Idots should have been removed"
+    | Ast0.Idots(dots,whencode) ->
+       let dots = mcode dots in
+       let whencode = get_option initialiser whencode in
+       Ast.Idots(dots,whencode)
     | Ast0.OptIni(ini) -> Ast.OptIni(initialiser ini)
     | Ast0.UniqueIni(ini) -> Ast.UniqueIni(initialiser ini))
 
@@ -562,15 +722,14 @@ and designator = function
 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.VoidParam(ty) -> Ast.VoidParam(typeC false ty)
+    | Ast0.Param(ty,id) ->
+       let allminus = check_allminus.VT0.combiner_rec_parameter p in
+       Ast.Param(typeC allminus 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.MetaParamList(name,lenname,_) ->
+       Ast.MetaParamList(mcode name,do_lenname lenname,unitary,false)
     | Ast0.PComma(cm) -> Ast.PComma(mcode cm)
     | Ast0.Pdots(dots) -> Ast.Pdots(mcode dots)
     | Ast0.Pcircles(dots) -> Ast.Pcircles(mcode dots)
@@ -598,10 +757,10 @@ and statement s =
     rewrap_stmt s
       (match Ast0.unwrap s with
        Ast0.Decl((_,bef),decl) ->
+         let allminus = check_allminus.VT0.combiner_rec_statement s in
          Ast.Atomic(rewrap_rule_elem s
-                      (Ast.Decl(convert_mcodekind (-1) bef,
-                                check_allminus.VT0.combiner_rec_statement s,
-                                declaration decl)))
+                      (Ast.Decl(convert_allminus_mcodekind allminus bef,
+                                allminus,declaration decl)))
       | Ast0.Seq(lbrace,body,rbrace) ->
          let lbrace = mcode lbrace in
          let body = dots (statement seqible) body in
@@ -612,14 +771,15 @@ and statement s =
                  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.ExprStatement
+                         (get_option 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 (-1) aft))
-      | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(_,aft)) ->
+            ([],[],[],convert_fake_mcode aft))
+      | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
          let els = mcode els in
          Ast.IfThenElse
            (rewrap_rule_elem s
@@ -627,13 +787,13 @@ and statement s =
             statement Ast.NotSequencible branch1,
             tokenwrap els s (Ast.Else(els)),
             statement Ast.NotSequencible branch2,
-            ([],[],[],convert_mcodekind (-1) aft))
-      | Ast0.While(wh,lp,exp,rp,body,(_,aft)) ->
+            ([],[],[],convert_fake_mcode 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 (-1) aft))
+                   ([],[],[],convert_fake_mcode 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)),
@@ -641,38 +801,38 @@ and statement s =
                 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)) ->
+      | Ast0.For(fr,lp,first,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 first = forinfo first 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 (-1) aft))
-      | Ast0.Iterator(nm,lp,args,rp,body,(_,aft)) ->
+                   (Ast.ForHeader(fr,lp,first,exp2,sem2,exp3,rp)),
+                 body,([],[],[],convert_fake_mcode 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 (-1) aft))
-      |        Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
+                   ([],[],[],convert_fake_mcode aft))
+      |        Ast0.Switch(switch,lp,exp,rp,lb,decls,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 decls = dots (statement seqible) decls 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,
+                    decls,cases,
                     tokenwrap rb s (Ast.SeqEnd(rb)))
       | Ast0.Break(br,sem) ->
          Ast.Atomic(rewrap_rule_elem s (Ast.Break(mcode br,mcode sem)))
@@ -695,6 +855,8 @@ and statement s =
       | Ast0.MetaStmtList(name,_) ->
          Ast.Atomic(rewrap_rule_elem s
                       (Ast.MetaStmtList(mcode name,unitary,false)))
+      | Ast0.AsStmt(stmt,asstmt) ->
+         Ast.AsStmt(statement seqible stmt,statement seqible asstmt)
       | Ast0.TopExp(exp) ->
          Ast.Atomic(rewrap_rule_elem s (Ast.TopExp(expression exp)))
       | Ast0.Exp(exp) ->
@@ -702,13 +864,15 @@ and statement s =
       | 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)))
+         let allminus = check_allminus.VT0.combiner_rec_statement s in
+         Ast.Atomic(rewrap_rule_elem s (Ast.Ty(typeC allminus 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) ->
+      | Ast0.Nest(starter,rule_elem_dots,ender,whn,multi) ->
          Ast.Nest
-           (statement_dots Ast.Sequencible rule_elem_dots,
+           (mcode starter,statement_dots Ast.Sequencible rule_elem_dots,
+            mcode ender,
             List.map
               (whencode (statement_dots Ast.Sequencible)
                 (statement Ast.NotSequencible))
@@ -749,13 +913,16 @@ and statement s =
          let rbrace = mcode rbrace in
          let allminus = check_allminus.VT0.combiner_rec_statement s in
          Ast.FunDecl(rewrap_rule_elem s
-                       (Ast.FunHeader(convert_mcodekind (-1) bef,
-                                      allminus,fi,name,lp,params,rp)),
+                       (Ast.FunHeader
+                          (convert_allminus_mcodekind allminus bef,
+                           allminus,fi,name,lp,params,rp)),
                      tokenwrap lbrace s (Ast.SeqStart(lbrace)),
                      body,
                      tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
       |        Ast0.Include(inc,str) ->
          Ast.Atomic(rewrap_rule_elem s (Ast.Include(mcode inc,mcode str)))
+      |        Ast0.Undef(def,id) ->
+         Ast.Atomic(rewrap_rule_elem s (Ast.Undef(mcode def,ident id)))
       | Ast0.Define(def,id,params,body) ->
          Ast.Define
            (rewrap_rule_elem s
@@ -875,9 +1042,21 @@ and statement s =
 
   statement Ast.Sequencible s
 
+and forinfo fi =
+  match Ast0.unwrap fi with
+    Ast0.ForExp(exp1,sem1) ->
+      let exp1 = get_option expression exp1 in
+      let sem1 = mcode sem1 in
+      Ast.ForExp(exp1,sem1)
+  | Ast0.ForDecl ((_,bef),decl) ->
+      let allminus =
+       check_allminus.VT0.combiner_rec_declaration decl in
+      Ast.ForDecl (convert_allminus_mcodekind allminus bef,
+                  allminus, declaration decl)
+
 and fninfo = function
     Ast0.FStorage(stg) -> Ast.FStorage(mcode stg)
-  | Ast0.FType(ty) -> Ast.FType(typeC ty)
+  | Ast0.FType(ty) -> Ast.FType(typeC false ty)
   | Ast0.FInline(inline) -> Ast.FInline(mcode inline)
   | Ast0.FAttr(attr) -> Ast.FAttr(mcode attr)
 
@@ -899,6 +1078,10 @@ and case_line c =
        let colon = mcode colon in
        let code = dots statement code in
        Ast.CaseLine(rewrap c no_isos (Ast.Case(case,exp,colon)),code)
+    | Ast0.DisjCase(_,case_lines,_,_) ->
+       failwith "not supported"
+       (*Ast.CaseLine(Ast.DisjRuleElem(List.map case_line case_lines))*)
+
     | Ast0.OptCase(case) -> Ast.OptCase(case_line case))
 
 and statement_dots l = dots statement l
@@ -917,17 +1100,19 @@ and anything = function
   | 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.TypeCTag(d) -> Ast.FullTypeTag(typeC false 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.ForInfoTag(d) -> Ast.ForInfoTag(forinfo 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"
+  | Ast0.HiddenVarTag _ -> failwith "not possible"
 
 (* --------------------------------------------------------------------- *)
 (* Function declaration *)
@@ -938,11 +1123,10 @@ and top_level t =
     (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.NONDECL(stmt) -> Ast.NONDECL(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")
+    | Ast0.OTHER(_) | Ast0.TOPCODE(_) -> failwith "eliminated by top_level")
 
 (* --------------------------------------------------------------------- *)
 (* Entry point for minus code *)