Coccinelle release-1.0.0-rc11
[bpt/coccinelle.git] / parsing_cocci / single_statement.ml
index 847a83c..cc0d180 100644 (file)
@@ -1,23 +1,27 @@
 (*
-* 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.
-*)
+ * 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.
+ *)
 
 
 (* detect statements that are between dots in the minus code, because they
@@ -26,6 +30,7 @@ may need a special treatment if they are if branches *)
 module Ast0 = Ast0_cocci
 module Ast = Ast_cocci
 module V0 = Visitor_ast0
+module VT0 = Visitor_ast0_types
 
 (* --------------------------------------------------------------------- *)
 (* --------------------------------------------------------------------- *)
@@ -44,7 +49,7 @@ let right_dots f l =
 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.PLUS -> failwith "not possible"
   | Ast0.CONTEXT mc ->
       (match !mc with
        (Ast.BEFORE _,_,_) -> true
@@ -54,7 +59,7 @@ let modif_before_mcode mc =
 
 let modif_after_mcodekind = function
     Ast0.MINUS mc -> true (*conservative; don't want to hunt right for + code*)
-  | Ast0.PLUS -> failwith "not possible"
+  | Ast0.PLUS -> failwith "not possible"
   | Ast0.CONTEXT mc ->
       (match !mc with
        (Ast.AFTER _,_,_) -> true
@@ -73,14 +78,14 @@ let any_statements =
 
 let modif_before x =
   match Ast0.get_mcodekind x with
-    Ast0.PLUS -> failwith "not possible"
+    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)]],_) ->
+       ((Ast.REPLACEMENT([[Ast.StatementTag(s)]],c)) as old,ti) ->
          (match Ast.unwrap s with
            Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
-         | _ -> false)
+         | _ -> mc := (old,ti); false)
       |        (_,_) -> true)
   | Ast0.CONTEXT mc | Ast0.MIXED mc ->
       (match !mc with
@@ -90,32 +95,45 @@ let modif_before x =
 
 let modif_after x =
   match Ast0.get_mcodekind x with
-    Ast0.PLUS -> failwith "not possible"
+    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)]],_) ->
+       ((Ast.REPLACEMENT([[Ast.StatementTag(s)]],count)) as old,ti) ->
          (match Ast.unwrap s with
            Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
-         | _ -> false)
-      |        (l,_) -> any_statements l)
+         | _ -> mc := (old,ti); false)
+      |        (Ast.REPLACEMENT(l,_),_) when any_statements l -> true
+      |        (l,ti) -> mc := (l,ti); false)
   | Ast0.CONTEXT mc | Ast0.MIXED mc ->
       (match !mc with
        (Ast.AFTER _,_,_) -> true
       |        (Ast.BEFOREAFTER _,_,_) -> true
-      |        _ -> false)    
+      |        _ -> 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.MetaId(name,_,_,_) -> modif_before_mcode name
   | Ast0.MetaFunc(name,_,_) -> modif_before_mcode name
   | Ast0.MetaLocalFunc(name,_,_) -> modif_before_mcode name
+  | Ast0.DisjId(_,id_list,_,_) -> List.exists left_ident id_list
   | Ast0.OptIdent(id) -> left_ident id
   | Ast0.UniqueIdent(id) -> left_ident id
 
+let rec right_ident i =
+  modif_after i or
+  match Ast0.unwrap i with
+    Ast0.Id(name) -> modif_after_mcode name
+  | Ast0.MetaId(name,_,_,_) -> modif_after_mcode name
+  | Ast0.MetaFunc(name,_,_) -> modif_after_mcode name
+  | Ast0.MetaLocalFunc(name,_,_) -> modif_after_mcode name
+  | Ast0.DisjId(_,id_list,_,_) -> List.exists right_ident id_list
+  | Ast0.OptIdent(id) -> right_ident id
+  | Ast0.UniqueIdent(id) -> right_ident id
+
 (* --------------------------------------------------------------------- *)
 (* Expression *)
 
@@ -126,6 +144,7 @@ let rec left_expression e =
   | 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.Sequence(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
@@ -140,6 +159,7 @@ let rec left_expression e =
   | 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.Constructor(lp,ty,rp,init) -> modif_before_mcode lp
   | Ast0.MetaErr(name,_,_) -> modif_before_mcode name
   | Ast0.MetaExpr(name,_,ty,_,_) -> modif_before_mcode name
   | Ast0.MetaExprList(name,_,_) -> modif_before_mcode name
@@ -150,6 +170,7 @@ let rec left_expression e =
   | Ast0.Edots(dots,_) | Ast0.Ecircles(dots,_) | Ast0.Estars(dots,_) -> false
   | Ast0.OptExp(exp) -> left_expression exp
   | Ast0.UniqueExp(exp) -> left_expression exp
+  | Ast0.AsExpr _ -> failwith "not possible"
 
 (* --------------------------------------------------------------------- *)
 (* Types *)
@@ -158,14 +179,15 @@ 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.BaseType(ty,strings) -> modif_before_mcode (List.hd strings)
+  | Ast0.Signed(sgn,ty) -> 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.EnumName(kind,name) -> modif_before_mcode kind
+  | Ast0.EnumDef(ty,lb,ids,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
@@ -173,6 +195,8 @@ and left_typeC t =
   | Ast0.DisjType(lp,types,mids,rp) -> List.exists left_typeC types
   | Ast0.OptType(ty) -> left_typeC ty
   | Ast0.UniqueType(ty) -> left_typeC ty
+  | Ast0.AsType _ -> failwith "not possible"
+
 
 (* --------------------------------------------------------------------- *)
 (* Variable declaration *)
@@ -182,30 +206,40 @@ and left_typeC t =
 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.MetaDecl(name,_) | Ast0.MetaField(name,_)
+  | Ast0.MetaFieldList(name,_,_) ->
+      modif_before_mcode name
+  | 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.MacroDeclInit(name,lp,args,rp,eq,ini,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
+  | Ast0.AsDecl _ -> failwith "not possible"
 
 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.MetaDecl(name,_) | Ast0.MetaField(name,_)
+  | Ast0.MetaFieldList(name,_,_) ->
+      modif_before_mcode name
+  | 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.MacroDeclInit(name,lp,args,rp,eq,ini,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
+  | Ast0.AsDecl _ -> failwith "not possible"
 
 (* --------------------------------------------------------------------- *)
 (* Top-level code *)
@@ -217,7 +251,8 @@ and left_statement s =
       (* 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.ExprStatement(Some exp,sem) -> left_expression exp
+  | Ast0.ExprStatement(None,sem) -> modif_before_mcode sem
   | 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
@@ -226,7 +261,8 @@ and left_statement s =
   | 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.Switch(switch,lp,exp,rp,lb,decls,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
@@ -245,9 +281,11 @@ and left_statement s =
   | 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.Undef(def,id) -> modif_before_mcode def
   | Ast0.Define(def,id,params,body) -> modif_before_mcode def
   | Ast0.OptStm(re) -> left_statement re
   | Ast0.UniqueStm(re) -> left_statement re
+  | Ast0.AsStmt _ -> failwith "not possible"
 
 and right_statement s =
   modif_after s or
@@ -266,7 +304,7 @@ and right_statement s =
       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.Switch(switch,lp,exp,rp,lb,decls,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
@@ -285,9 +323,11 @@ and right_statement s =
   | 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.Undef(def,id) -> right_ident id
   | Ast0.Define(def,id,params,body) -> right_dots right_statement body
   | Ast0.OptStm(re) -> right_statement re
   | Ast0.UniqueStm(re) -> right_statement re
+  | Ast0.AsStmt _ -> failwith "not possible"
 
 (* --------------------------------------------------------------------- *)
 
@@ -302,16 +342,16 @@ let rec adding_something s =
     Ast0.MINUS(mc) ->
       (match !mc with
        (* do better for the common case of replacing a stmt by another one *)
-       ([[Ast.StatementTag(s)]],_) ->
+       ((Ast.REPLACEMENT([[Ast.StatementTag(s)]],c)) as old,ti) ->
          (match Ast.unwrap s with
            Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
-         | _ -> false)
+         | _ -> mc := (old,ti); 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) (*&&
+      not(contains_only_minus.VT0.combiner_rec_statement s) (*&&
       (left_statement s) or (right_statement s)*)
   | _ -> failwith "unexpected plus code"
 
@@ -322,11 +362,11 @@ and contains_only_minus =
   let mcodekind = function
       Ast0.MINUS(mc) ->
        (match !mc with
-         ([],_) -> true
+         (Ast.NOREPLACEMENT,_) -> true
        | _ -> false)
     | Ast0.CONTEXT(mc) -> false
     | _ -> false in
-  let mcode (_,_,_,mc,_) = mcodekind mc in
+  let mcode (_,_,_,mc,_,_) = mcodekind mc in
 
   let donothing r k e = mcodekind (Ast0.get_mcodekind e) && k e in
 
@@ -335,40 +375,53 @@ and contains_only_minus =
       Ast0.DOTS([]) | Ast0.CIRCLES([]) | Ast0.STARS([]) -> true
     | _ -> k e in
 
+  let identifier r k e =
+    mcodekind (Ast0.get_mcodekind e) &&
+    match Ast0.unwrap e with
+      Ast0.DisjId(starter,id_list,mids,ender) ->
+       List.for_all r.VT0.combiner_rec_ident id_list
+    | _ -> 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
+       List.for_all r.VT0.combiner_rec_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
+       List.for_all r.VT0.combiner_rec_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
+       List.for_all r.VT0.combiner_rec_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
+       List.for_all r.VT0.combiner_rec_statement_dots statement_dots_list
     | _ -> k e in
 
-  V0.combiner bind option_default
+  let case_line r k e =
+    mcodekind (Ast0.get_mcodekind e) &&
+    match Ast0.unwrap e with
+      Ast0.DisjCase(starter,case_list,mids,ender) ->
+       List.for_all r.VT0.combiner_rec_case_line case_list
+    | _ -> k e in
+
+  V0.flat_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
+    identifier expression typeC donothing donothing declaration
+    statement case_line donothing
 
 
 (* needs a special case when there is a Disj or an empty DOTS *)
@@ -388,41 +441,61 @@ 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 s =
+    (Iso_pattern.rebuild_mcode None).VT0.rebuilder_rec_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))
+       let inner_text =
+         match text with
+           Ast.NOREPLACEMENT -> [[Ast.mkToken "{}"]]
+         | Ast.REPLACEMENT(anythings,Ast.ONE) ->
+             [Ast.mkToken "{"]::anythings@[[Ast.mkToken "}"]]
+         | Ast.REPLACEMENT(anythings,Ast.MANY) ->
+             failwith "++ not supported when braces must be added" in
+       Ast0.MINUS(ref(Ast.REPLACEMENT(inner_text,Ast.ONE),tinfo))
     | Ast0.CONTEXT(mc) ->
        let (text,tinfo1,tinfo2) = !mc in
        let new_text =
+         (* this is going to be a mess if we allow it to be iterable...
+            there would be one level of braces for every added things.
+            need to come up with something better, or just add {} in the
+            source code. *)
          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.BEFORE(bef,_) ->
+             Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]],
+                             Ast.ONE)
+         | Ast.AFTER(aft,_) ->
+             Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]],
+                             Ast.ONE)
+         | Ast.BEFOREAFTER(bef,aft,_) ->
+             Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]],
+                             Ast.ONE)
          | Ast.NOTHING ->
-             Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) in
+             Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]],
+                             Ast.ONE) 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.BEFORE(bef,_) ->
+             Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,[[Ast.mkToken "}"]],
+                             Ast.ONE)
+         | Ast.AFTER(aft,_) ->
+             Ast.BEFOREAFTER([[Ast.mkToken "{"]],aft@[[Ast.mkToken "}"]],
+                             Ast.ONE)
+         | Ast.BEFOREAFTER(bef,aft,_) ->
+             Ast.BEFOREAFTER([Ast.mkToken "{"]::bef,aft@[[Ast.mkToken "}"]],
+                             Ast.ONE)
          | Ast.NOTHING ->
-             Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]]) in
+             Ast.BEFOREAFTER([[Ast.mkToken "{"]],[[Ast.mkToken "}"]],
+                             Ast.ONE) in
        Ast0.MIXED(ref(new_text,tinfo1,tinfo2))
     | _ -> failwith "unexpected plus code" in
   Ast0.set_mcodekind s new_mcodekind;
-  Compute_lines.statement s
+  Compute_lines.compute_statement_lines true s
 
 (* ---------------------------------------------------------------------- *)
 
@@ -439,7 +512,8 @@ let all_minus s =
 
 let rec unchanged_minus s =
   match Ast0.get_mcodekind s with
-    Ast0.MINUS(mc) -> (match !mc with ([],_) -> true | _ -> false)
+    Ast0.MINUS(mc) ->
+      (match !mc with (Ast.NOREPLACEMENT,_) -> true | _ -> false)
   | _ -> false
 
 let rec do_branch s =
@@ -518,12 +592,13 @@ let rec statement dots_before dots_after s =
       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) ->
+  | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
       do_one
        (Ast0.rewrap s
-          (Ast0.Switch(switch,lp,exp,rp,lb,
+          (Ast0.Switch(switch,lp,exp,rp,lb,decls,
                        Ast0.rewrap cases
-                         (Ast0.DOTS(List.map case_line (Ast0.undots 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
@@ -540,22 +615,28 @@ let rec statement dots_before dots_after s =
                     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))
+      (match Ast0.get_mcode_mcodekind starter with
+       Ast0.MINUS _ -> (* everything removed, like -... *) s
+      |        _ ->
+         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.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.Undef(def,id) -> s (* same as include *)
   | Ast0.Define(def,id,params,body) -> s (* same as include *)
-  | Ast0.OptStm(re) -> 
+  | 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))
+  | Ast0.AsStmt _ -> failwith "not possible"
 
 and case_line c =
   Ast0.rewrap c
@@ -564,8 +645,10 @@ and case_line c =
        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.DisjCase(starter,case_lines,mids,ender) ->
+       Ast0.DisjCase(starter,List.map case_line case_lines,mids,ender)
     | Ast0.OptCase(case) -> Ast0.OptCase(case_line c))
-  
+
 and do_statement_dots dots_before dots_after = function
     [] -> []
   | [x] -> [statement dots_before dots_after x]
@@ -577,7 +660,7 @@ and do_statement_dots dots_before dots_after = function
   | 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
@@ -591,7 +674,7 @@ and statement_dots dots_before dots_after d =
 let top_level t =
   Ast0.rewrap t
     (match Ast0.unwrap t with
-      Ast0.DECL(stmt_dots) -> Ast0.DECL(statement true true stmt_dots)
+      Ast0.NONDECL(stmt_dots) -> Ast0.NONDECL(statement true true stmt_dots)
     | Ast0.CODE(stmt_dots) -> Ast0.CODE(statement_dots true true stmt_dots)
     | t -> t)