- Try to do better pretty printing when array elements are individually
[bpt/coccinelle.git] / parsing_cocci / context_neg.ml
index 686b727..26cb99f 100644 (file)
@@ -1,5 +1,7 @@
 (*
 (*
- * Copyright 2010, INRIA, University of Copenhagen
+ * 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
  * 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
@@ -22,6 +24,7 @@
  *)
 
 
  *)
 
 
+# 0 "./context_neg.ml"
 (* 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,
 (* 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,
@@ -54,12 +57,14 @@ let set_mcodekind x 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.DeclTag(d) -> Ast0.set_mcodekind d mcodekind
   | Ast0.InitTag(d) -> Ast0.set_mcodekind d mcodekind
   | Ast0.StmtTag(d) -> Ast0.set_mcodekind d mcodekind
+  | Ast0.ForInfoTag(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.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"
+  | Ast0.MetaPosTag(p) -> failwith "invisible at this stage"
+  | Ast0.HiddenVarTag(p) -> failwith "hiddenvar only within iso phase"
 
 let set_index x index =
   match x with
 
 let set_index x index =
   match x with
@@ -78,12 +83,14 @@ let set_index x 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.InitTag(d) -> Ast0.set_index d index
   | Ast0.DeclTag(d) -> Ast0.set_index d index
   | Ast0.StmtTag(d) -> Ast0.set_index d index
+  | Ast0.ForInfoTag(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.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"
+  | Ast0.MetaPosTag(p) -> failwith "invisible at this stage"
+  | Ast0.HiddenVarTag(p) -> failwith "hiddenvar only within iso phase"
 
 let get_index = function
     Ast0.DotsExprTag(d) -> Index.expression_dots d
 
 let get_index = function
     Ast0.DotsExprTag(d) -> Index.expression_dots d
@@ -101,12 +108,14 @@ let get_index = function
   | Ast0.InitTag(d) -> Index.initialiser d
   | Ast0.DeclTag(d) -> Index.declaration d
   | Ast0.StmtTag(d) -> Index.statement d
   | Ast0.InitTag(d) -> Index.initialiser d
   | Ast0.DeclTag(d) -> Index.declaration d
   | Ast0.StmtTag(d) -> Index.statement d
+  | Ast0.ForInfoTag(d) -> Index.forinfo 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.CaseLineTag(d) -> Index.case_line d
   | Ast0.TopTag(d) -> Index.top_level d
   | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
   | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
   | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
-  | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
+  | Ast0.MetaPosTag(p) -> failwith "invisible at this stage"
+  | Ast0.HiddenVarTag(p) -> failwith "hiddenvar only within iso phase"
 
 (* --------------------------------------------------------------------- *)
 (* Collect the line numbers of the plus code.  This is used for disjunctions.
 
 (* --------------------------------------------------------------------- *)
 (* Collect the line numbers of the plus code.  This is used for disjunctions.
@@ -150,7 +159,7 @@ let collect_plus_lines top =
       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
       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
+      donothing donothing donothing in
   fn.VT0.combiner_rec_top_level top
 
 (* --------------------------------------------------------------------- *)
   fn.VT0.combiner_rec_top_level top
 
 (* --------------------------------------------------------------------- *)
@@ -330,6 +339,13 @@ let classify is_minus all_marked table code =
 
   (* no whencode in plus tree so have to drop it *)
   (* need special cases for dots, nests, and disjs *)
 
   (* no whencode in plus tree so have to drop it *)
   (* need special cases for dots, nests, and disjs *)
+  let ident r k e =
+    compute_result Ast0.ident e
+      (match Ast0.unwrap e with
+       Ast0.DisjId(starter,id_list,_,ender) ->
+         disj_cases e starter id_list r.VT0.combiner_rec_ident ender
+      |        _ -> k e) in
+
   let expression r k e =
     compute_result Ast0.expr e
       (match Ast0.unwrap e with
   let expression r k e =
     compute_result Ast0.expr e
       (match Ast0.unwrap e with
@@ -347,6 +363,7 @@ let classify is_minus all_marked table code =
 
   (* 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 *)
 
   (* 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 *)
+  (* actually, DisjDecl now allowed in source struct decls *)
   let declaration r k e =
     compute_result Ast0.decl e
       (match Ast0.unwrap e with
   let declaration r k e =
     compute_result Ast0.decl e
       (match Ast0.unwrap e with
@@ -416,18 +433,19 @@ let classify is_minus all_marked table code =
       | Ast0.Stars(dots,whencode) ->
          k (Ast0.rewrap s (Ast0.Stars(dots,[])))
       | Ast0.Disj(starter,statement_dots_list,_,ender) ->
       | 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.VT0.combiner_rec_statement_dots
+         disj_cases s starter statement_dots_list
+           r.VT0.combiner_rec_statement_dots
            ender
        (* cases for everything with extra mcode *)
       |        Ast0.FunDecl((info,bef),_,_,_,_,_,_,_,_)
       | Ast0.Decl((info,bef),_) ->
          bind (nc_mcode ((),(),info,bef,(),-1)) (k s)
            ender
        (* cases for everything with extra mcode *)
       |        Ast0.FunDecl((info,bef),_,_,_,_,_,_,_,_)
       | Ast0.Decl((info,bef),_) ->
          bind (nc_mcode ((),(),info,bef,(),-1)) (k s)
-      | Ast0.IfThen(_,_,_,_,_,(info,aft))
-      | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft))
-      | Ast0.Iterator(_,_,_,_,_,(info,aft))
-      | Ast0.While(_,_,_,_,_,(info,aft))
-      | Ast0.For(_,_,_,_,_,_,_,_,_,(info,aft)) ->
-         bind (k s) (nc_mcode ((),(),info,aft,(),-1))
+      | Ast0.IfThen(_,_,_,_,_,(info,aft,adj))
+      | Ast0.IfThenElse(_,_,_,_,_,_,_,(info,aft,adj))
+      | Ast0.Iterator(_,_,_,_,_,(info,aft,adj))
+      | Ast0.While(_,_,_,_,_,(info,aft,adj))
+      | Ast0.For(_,_,_,_,_,_,_,_,(info,aft,adj)) ->
+         bind (k s) (nc_mcode ((),(),info,aft,(),adj))
       |        _ -> k s
 
 ) in
       |        _ -> k s
 
 ) in
@@ -440,8 +458,8 @@ let classify is_minus all_marked table code =
       (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.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 case_line (do_top Ast0.top) in
+      ident expression typeC initialiser param declaration
+      statement (do_nothing Ast0.forinfo) case_line (do_top Ast0.top) in
   combiner.VT0.combiner_rec_top_level code
 
 (* --------------------------------------------------------------------- *)
   combiner.VT0.combiner_rec_top_level code
 
 (* --------------------------------------------------------------------- *)
@@ -469,12 +487,17 @@ let dots fn d1 d2 =
 let rec equal_ident i1 i2 =
   match (Ast0.unwrap i1,Ast0.unwrap i2) with
     (Ast0.Id(name1),Ast0.Id(name2)) -> equal_mcode name1 name2
 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,_,_)) ->
+  | (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
       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.DisjId(starter1,_,mids1,ender1),
+     Ast0.DisjId(starter2,_,mids2,ender2)) ->
+      equal_mcode starter1 starter2 &&
+      List.for_all2 equal_mcode mids1 mids2 &&
+      equal_mcode ender1 ender2
   | (Ast0.OptIdent(_),Ast0.OptIdent(_)) -> true
   | (Ast0.UniqueIdent(_),Ast0.UniqueIdent(_)) -> true
   | _ -> false
   | (Ast0.OptIdent(_),Ast0.OptIdent(_)) -> true
   | (Ast0.UniqueIdent(_),Ast0.UniqueIdent(_)) -> true
   | _ -> false
@@ -487,6 +510,8 @@ let rec equal_expression e1 e2 =
       equal_mcode lp1 lp2 && equal_mcode rp1 rp2
   | (Ast0.Assignment(_,op1,_,_),Ast0.Assignment(_,op2,_,_)) ->
       equal_mcode op1 op2
       equal_mcode lp1 lp2 && equal_mcode rp1 rp2
   | (Ast0.Assignment(_,op1,_,_),Ast0.Assignment(_,op2,_,_)) ->
       equal_mcode op1 op2
+  | (Ast0.Sequence(_,op1,_),Ast0.Sequence(_,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.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
@@ -508,6 +533,8 @@ let rec equal_expression e1 e2 =
   | (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.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.Constructor(lp1,_,rp1,_),Ast0.Constructor(lp2,_,rp2,_)) ->
+      equal_mcode lp1 lp2 && equal_mcode rp1 rp2
   | (Ast0.MetaErr(name1,_,_),Ast0.MetaErr(name2,_,_))
   | (Ast0.MetaExpr(name1,_,_,_,_),Ast0.MetaExpr(name2,_,_,_,_))
   | (Ast0.MetaExprList(name1,_,_),Ast0.MetaExprList(name2,_,_)) ->
   | (Ast0.MetaErr(name1,_,_),Ast0.MetaErr(name2,_,_))
   | (Ast0.MetaExpr(name1,_,_,_,_),Ast0.MetaExpr(name2,_,_,_,_))
   | (Ast0.MetaExprList(name1,_,_),Ast0.MetaExprList(name2,_,_)) ->
@@ -541,6 +568,8 @@ let rec equal_typeC t1 t2 =
       equal_mcode lb1 lb2 && equal_mcode rb1 rb2
   | (Ast0.EnumName(kind1,_),Ast0.EnumName(kind2,_)) ->
       equal_mcode kind1 kind2
       equal_mcode lb1 lb2 && equal_mcode rb1 rb2
   | (Ast0.EnumName(kind1,_),Ast0.EnumName(kind2,_)) ->
       equal_mcode kind1 kind2
+  | (Ast0.EnumDef(_,lb1,_,rb1),Ast0.EnumDef(_,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)) ->
   | (Ast0.StructUnionName(kind1,_),Ast0.StructUnionName(kind2,_)) ->
       equal_mcode kind1 kind2
   | (Ast0.FunctionType(ty1,lp1,p1,rp1),Ast0.FunctionType(ty2,lp2,p2,rp2)) ->
@@ -562,18 +591,29 @@ let rec equal_typeC t1 t2 =
 
 let equal_declaration d1 d2 =
   match (Ast0.unwrap d1,Ast0.unwrap d2) with
 
 let equal_declaration d1 d2 =
   match (Ast0.unwrap d1,Ast0.unwrap d2) with
-    (Ast0.Init(stg1,_,_,eq1,_,sem1),Ast0.Init(stg2,_,_,eq2,_,sem2)) ->
+    (Ast0.MetaDecl(name1,_),Ast0.MetaDecl(name2,_))
+  | (Ast0.MetaField(name1,_),Ast0.MetaField(name2,_))
+  | (Ast0.MetaFieldList(name1,_,_),Ast0.MetaFieldList(name2,_,_)) ->
+      equal_mcode name1 name2
+  | (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
       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)) ->
+  | (Ast0.MacroDecl(nm1,lp1,_,rp1,sem1),Ast0.MacroDecl(nm2,lp2,_,rp2,sem2))->
       equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode sem1 sem2
       equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode sem1 sem2
+  | (Ast0.MacroDeclInit(nm1,lp1,_,rp1,eq1,_,sem1),
+     Ast0.MacroDeclInit(nm2,lp2,_,rp2,eq2,_,sem2))->
+      equal_mcode lp1 lp2 && equal_mcode rp1 rp2 && equal_mcode eq1 eq2
+        && 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.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"
+  | (Ast0.DisjDecl(starter1,_,mids1,ender1),
+     Ast0.DisjDecl(starter2,_,mids2,ender2)) ->
+       equal_mcode starter1 starter2 &&
+       List.for_all2 equal_mcode mids1 mids2 &&
+       equal_mcode ender1 ender2
   | _ -> false
 
 let equal_designator d1 d2 =
   | _ -> false
 
 let equal_designator d1 d2 =
@@ -592,8 +632,12 @@ let equal_initialiser i1 i2 =
   match (Ast0.unwrap i1,Ast0.unwrap i2) with
     (Ast0.MetaInit(name1,_),Ast0.MetaInit(name2,_)) ->
       equal_mcode name1 name2
   match (Ast0.unwrap i1,Ast0.unwrap i2) with
     (Ast0.MetaInit(name1,_),Ast0.MetaInit(name2,_)) ->
       equal_mcode name1 name2
+  | (Ast0.MetaInitList(name1,_,_),Ast0.MetaInitList(name2,_,_)) ->
+      equal_mcode name1 name2
   | (Ast0.InitExpr(_),Ast0.InitExpr(_)) -> true
   | (Ast0.InitExpr(_),Ast0.InitExpr(_)) -> true
-  | (Ast0.InitList(lb1,_,rb1),Ast0.InitList(lb2,_,rb2)) ->
+  | (Ast0.InitList(lb1,_,rb1,o1),Ast0.InitList(lb2,_,rb2,o2)) ->
+      (* can't compare orderedness, because this can differ between -
+        and + code *)
       (equal_mcode lb1 lb2) && (equal_mcode rb1 rb2)
   | (Ast0.InitGccExt(designators1,eq1,_),
      Ast0.InitGccExt(designators2,eq2,_)) ->
       (equal_mcode lb1 lb2) && (equal_mcode rb1 rb2)
   | (Ast0.InitGccExt(designators1,eq1,_),
      Ast0.InitGccExt(designators2,eq2,_)) ->
@@ -645,10 +689,16 @@ let rec equal_statement s1 s2 =
   | (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.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,_,_)) ->
+  | (Ast0.For(fr1,lp1,first1,_,sem21,_,rp1,_,_),
+     Ast0.For(fr2,lp2,first2,_,sem22,_,rp2,_,_)) ->
+       let first =
+        match (Ast0.unwrap first1,Ast0.unwrap first2) with
+          (Ast0.ForExp(_,sem1),Ast0.ForExp(_,sem2)) -> 
+            equal_mcode sem1 sem2
+        | (Ast0.ForDecl _,Ast0.ForDecl _) -> true
+        | _ -> false in
        equal_mcode fr1 fr2 && equal_mcode lp1 lp2 &&
        equal_mcode fr1 fr2 && equal_mcode lp1 lp2 &&
-       equal_mcode sem11 sem12 && equal_mcode sem21 sem22 &&
+       first && 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
        equal_mcode rp1 rp2
   | (Ast0.Iterator(nm1,lp1,_,rp1,_,_),Ast0.Iterator(nm2,lp2,_,rp2,_,_)) ->
       equal_mcode lp1 lp2 && equal_mcode rp1 rp2
@@ -687,6 +737,8 @@ let rec equal_statement s1 s2 =
   | (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.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.Undef(def1,_),Ast0.Undef(def2,_)) ->
+      equal_mcode def1 def2
   | (Ast0.Define(def1,_,_,_),Ast0.Define(def2,_,_,_)) ->
       equal_mcode def1 def2
   | (Ast0.OptStm(_),Ast0.OptStm(_)) -> true
   | (Ast0.Define(def1,_,_,_),Ast0.Define(def2,_,_,_)) ->
       equal_mcode def1 def2
   | (Ast0.OptStm(_),Ast0.OptStm(_)) -> true
@@ -717,7 +769,7 @@ let equal_case_line c1 c2 =
 
 let rec equal_top_level t1 t2 =
   match (Ast0.unwrap t1,Ast0.unwrap t2) with
 
 let rec equal_top_level t1 t2 =
   match (Ast0.unwrap t1,Ast0.unwrap t2) with
-    (Ast0.DECL(_),Ast0.DECL(_)) -> true
+    (Ast0.NONDECL(_),Ast0.NONDECL(_)) -> 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.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
@@ -781,7 +833,7 @@ let contextify_all =
     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
     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
 
 let contextify_whencode =
   let bind x y = () in
 
 let contextify_whencode =
   let bind x y = () in
@@ -837,10 +889,11 @@ let plus_table =
 
 let iscode t =
   match Ast0.unwrap t with
 
 let iscode t =
   match Ast0.unwrap t with
-    Ast0.DECL(_) -> true
+    Ast0.NONDECL(_) -> true
   | Ast0.FILEINFO(_) -> true
   | Ast0.ERRORWORDS(_) -> false
   | Ast0.CODE(_) -> true
   | Ast0.FILEINFO(_) -> true
   | Ast0.ERRORWORDS(_) -> false
   | Ast0.CODE(_) -> true
+  | Ast0.TOPCODE(_)
   | Ast0.OTHER(_) -> failwith "unexpected top level code"
 
 (* ------------------------------------------------------------------- *)
   | Ast0.OTHER(_) -> failwith "unexpected top level code"
 
 (* ------------------------------------------------------------------- *)
@@ -854,7 +907,7 @@ let concat = function
          [] -> []
        | x::rest ->
            (match Ast0.unwrap x with
          [] -> []
        | x::rest ->
            (match Ast0.unwrap x with
-             Ast0.DECL(s) -> let stms = loop rest in s::stms
+             Ast0.NONDECL(s) -> let stms = loop rest in s::stms
            | Ast0.CODE(ss) ->
                let stms = loop rest in
                (match Ast0.unwrap ss with
            | Ast0.CODE(ss) ->
                let stms = loop rest in
                (match Ast0.unwrap ss with
@@ -935,14 +988,17 @@ let rec is_toplevel s =
     Ast0.Decl(_,e) -> true
   | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
   | Ast0.Disj(_,stmts,_,_) -> isall is_toplevel stmts
     Ast0.Decl(_,e) -> true
   | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
   | Ast0.Disj(_,stmts,_,_) -> isall is_toplevel stmts
-  | Ast0.ExprStatement(fc,_) ->
+  | Ast0.ExprStatement(Some fc,_) ->
       (match Ast0.unwrap fc with
        Ast0.FunCall(_,_,_,_) -> true
       |        _ -> false)
   | Ast0.Include(_,_) -> true
       (match Ast0.unwrap fc with
        Ast0.FunCall(_,_,_,_) -> true
       |        _ -> false)
   | Ast0.Include(_,_) -> true
+  | Ast0.Undef(_,_) -> true
   | Ast0.Define(_,_,_,_) -> true
   | _ -> false
 
   | Ast0.Define(_,_,_,_) -> true
   | _ -> false
 
+(* consider code and topcode to be the same; difference handled
+in top_level.ml *)
 let check_compatible m p =
   let fail _ =
     failwith
 let check_compatible m p =
   let fail _ =
     failwith
@@ -950,17 +1006,21 @@ let check_compatible m p =
         "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
         "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)) ->
+    (Ast0.NONDECL(decl1),Ast0.NONDECL(decl2)) ->
       if not (is_decl decl1 && is_decl decl2)
       then fail()
       if not (is_decl decl1 && is_decl decl2)
       then fail()
-  | (Ast0.DECL(decl1),Ast0.CODE(code2)) ->
+  | (Ast0.NONDECL(decl1),Ast0.CODE(code2)) ->
+      (* This is probably the only important case.  We don't want to
+        replace top-level declarations by arbitrary code. *)
       let v1 = is_decl decl1 in
       let v2 = List.for_all is_toplevel (Ast0.undots code2) in
       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)) ->
+      if !Flag.make_hrule = None && v1 && not v2
+      then fail()
+  | (Ast0.CODE(code1),Ast0.NONDECL(decl2)) ->
       let v1 = List.for_all is_toplevel (Ast0.undots code1) in
       let v2 = is_decl decl2 in
       let v1 = List.for_all is_toplevel (Ast0.undots code1) in
       let v2 = is_decl decl2 in
-      if v1 && not v2 then fail()
+      if v1 && not v2
+      then fail()
   | (Ast0.CODE(code1),Ast0.CODE(code2)) ->
       let v1 = isonly is_init code1 in
       let v2a = isonly is_init code2 in
   | (Ast0.CODE(code1),Ast0.CODE(code2)) ->
       let v1 = isonly is_init code1 in
       let v2a = isonly is_init code2 in
@@ -978,11 +1038,29 @@ let check_compatible m p =
          testers;
        let v1 = isonly is_fndecl code1 in
        let v2 = List.for_all is_toplevel (Ast0.undots code2) in
          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()
+       if !Flag.make_hrule = None && v1 && not v2
+       then fail()
   | (Ast0.FILEINFO(_,_),Ast0.FILEINFO(_,_)) -> ()
   | (Ast0.OTHER(_),Ast0.OTHER(_)) -> ()
   | _ -> fail()
 
   | (Ast0.FILEINFO(_,_),Ast0.FILEINFO(_,_)) -> ()
   | (Ast0.OTHER(_),Ast0.OTHER(_)) -> ()
   | _ -> fail()
 
+(* can't just remove expressions or types, not sure if all cases are needed. *)
+let check_complete m =
+   match Ast0.unwrap m with
+     Ast0.NONDECL(code) ->
+       if is_exp code or is_ty code
+       then
+        failwith
+          (Printf.sprintf "invalid minus starting on line %d"
+             (Ast0.get_line m))
+   | Ast0.CODE(code) ->
+       if isonly is_exp code or isonly is_ty code
+       then
+        failwith
+           (Printf.sprintf "invalid minus starting on line %d"
+              (Ast0.get_line m))
+   | _ -> ()
+
 (* ------------------------------------------------------------------- *)
 
 (* returns a list of corresponding minus and plus trees *)
 (* ------------------------------------------------------------------- *)
 
 (* returns a list of corresponding minus and plus trees *)
@@ -996,12 +1074,14 @@ let context_neg minus plus =
     | ([],l) ->
        failwith (Printf.sprintf "%d plus things remaining" (List.length l))
     | (minus,[]) ->
     | ([],l) ->
        failwith (Printf.sprintf "%d plus things remaining" (List.length l))
     | (minus,[]) ->
+       List.iter check_complete minus;
        plus_lines := [];
        let _ =
          List.map
            (function m ->
              classify true
        plus_lines := [];
        let _ =
          List.map
            (function m ->
              classify true
-               (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+               (function _ ->
+                 Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)))
                minus_table m)
            minus in
        []
                minus_table m)
            minus in
        []
@@ -1027,7 +1107,8 @@ let context_neg minus plus =
            collect_plus_lines p;
            let _ =
              classify true
            collect_plus_lines p;
            let _ =
              classify true
-               (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+               (function _ ->
+                 Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)))
                minus_table m in
            let _ = classify false (function c -> Ast0.PLUS c) plus_table p in
            traverse minus_table plus_table;
                minus_table m in
            let _ = classify false (function c -> Ast0.PLUS c) plus_table p in
            traverse minus_table plus_table;
@@ -1043,7 +1124,9 @@ let context_neg minus plus =
                plus_lines := [];
                let _ =
                  classify true
                plus_lines := [];
                let _ =
                  classify true
-                   (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
+                   (function _ ->
+                     Ast0.MINUS(ref(Ast.NOREPLACEMENT,
+                                    Ast0.default_token_info)))
                    minus_table m in
                loop(minus,pall)
              end
                    minus_table m in
                loop(minus,pall)
              end