Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / parsing_cocci / context_neg.ml
index 93de14b..eafd4d2 100644 (file)
@@ -1,23 +1,45 @@
 (*
-* 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 2005-2010, 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.
+ *)
+
+
+(*
+ * Copyright 2005-2010, 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.
+ *)
 
 
 (* Detects subtrees that are all minus/plus and nodes that are "binding
@@ -139,9 +161,9 @@ let collect_plus_lines top =
   let bind x y = () in
   let option_default = () in
   let donothing r k e = k e in
-  let mcode (_,_,info,mcodekind,_) =
+  let mcode (_,_,info,mcodekind,_,_) =
     match mcodekind with
-      Ast0.PLUS -> insert info.Ast0.pos_info.Ast0.line_start
+      Ast0.PLUS -> insert info.Ast0.pos_info.Ast0.line_start
     | _ -> () in
   let fn =
     V0.flat_combiner bind option_default
@@ -153,7 +175,8 @@ let collect_plus_lines top =
 
 (* --------------------------------------------------------------------- *)
 
-type kind = Neutral | AllMarked | NotAllMarked (* marked means + or - *)
+type kind =
+    Neutral | AllMarked of Ast.count | NotAllMarked (* marked means + or - *)
 
 (* --------------------------------------------------------------------- *)
 (* The first part analyzes each of the minus tree and the plus tree
@@ -176,7 +199,7 @@ type node =
 
 let kind2c = function
     Neutral -> "neutral"
-  | AllMarked -> "allmarked"
+  | AllMarked -> "allmarked"
   | NotAllMarked -> "notallmarked"
 
 let node2c = function
@@ -189,8 +212,8 @@ tokens *)
 let bind c1 c2 =
   let lub = function
       (k1,k2) when k1 = k2 -> k1
-    | (Neutral,AllMarked) -> AllMarked
-    | (AllMarked,Neutral) -> AllMarked
+    | (Neutral,AllMarked c) -> AllMarked c
+    | (AllMarked c,Neutral) -> AllMarked c
     | _ -> NotAllMarked in
   match (c1,c2) with
     (* token/token *)
@@ -228,30 +251,37 @@ let bind c1 c2 =
 let option_default = (*Bind(Neutral,[],[],[],[],[])*)
   Recursor(Neutral,[],[],[])
 
-let mcode (_,_,info,mcodekind,pos) =
+let mcode (_,_,info,mcodekind,pos,_) =
   let offset = info.Ast0.pos_info.Ast0.offset in
   match mcodekind with
-    Ast0.MINUS(_) -> Token(AllMarked,offset,mcodekind,[])
-  | Ast0.PLUS -> Token(AllMarked,offset,mcodekind,[])
+    Ast0.MINUS(_) -> Token(AllMarked Ast.ONE,offset,mcodekind,[])
+  | Ast0.PLUS c -> Token(AllMarked c,offset,mcodekind,[])
   | Ast0.CONTEXT(_) -> Token(NotAllMarked,offset,mcodekind,[offset])
   | _ -> failwith "not possible"
 
-let neutral_mcode (_,_,info,mcodekind,pos) =
+let neutral_mcode (_,_,info,mcodekind,pos,_) =
   let offset = info.Ast0.pos_info.Ast0.offset in
   match mcodekind with
     Ast0.MINUS(_) -> Token(Neutral,offset,mcodekind,[])
-  | Ast0.PLUS -> Token(Neutral,offset,mcodekind,[])
+  | Ast0.PLUS -> Token(Neutral,offset,mcodekind,[])
   | Ast0.CONTEXT(_) -> Token(Neutral,offset,mcodekind,[offset])
   | _ -> failwith "not possible"
 
 (* neutral for context; used for mcode in bef aft nodes that don't represent
 anything if they don't contain some information *)
-let nc_mcode (_,_,info,mcodekind,pos) =
-  let offset = info.Ast0.pos_info.Ast0.offset in
+let nc_mcode (_,_,info,mcodekind,pos,_) =
+  (* distinguish from the offset of some real token *)
+  let offset = (-1) * info.Ast0.pos_info.Ast0.offset in
   match mcodekind with
-    Ast0.MINUS(_) -> Token(AllMarked,offset,mcodekind,[])
-  | Ast0.PLUS -> Token(AllMarked,offset,mcodekind,[])
-  | Ast0.CONTEXT(_) -> Token(Neutral,offset,mcodekind,[offset])
+    Ast0.MINUS(_) -> Token(AllMarked Ast.ONE,offset,mcodekind,[])
+  | Ast0.PLUS c -> Token(AllMarked c,offset,mcodekind,[])
+  | Ast0.CONTEXT(_) ->
+      (* Unlike the other mcode cases, we drop the offset from the context
+        offsets.  This is because we don't know whether the term this is
+        associated with is - or context.  In any case, the context offsets are
+        used for identification, and this invisible node should not be needed
+        for this purpose. *)
+      Token(Neutral,offset,mcodekind,[])
   | _ -> failwith "not possible"
 
 let is_context = function Ast0.CONTEXT(_) -> true | _ -> false
@@ -262,9 +292,10 @@ let union_all l = List.fold_left Common.union_set [] l
 intermingled with plus code.  it is used in disj_cases *)
 let classify is_minus all_marked table code =
   let mkres builder k il tl bil btl l e =
-    (if k = AllMarked
-    then Ast0.set_mcodekind e (all_marked()) (* definitive *)
-    else
+    (match k with
+      AllMarked count ->
+       Ast0.set_mcodekind e (all_marked count) (* definitive *)
+    | _ ->
       let check_index il tl =
        if List.for_all is_context tl
        then
@@ -386,6 +417,13 @@ let classify is_minus all_marked table code =
          k (Ast0.rewrap i (Ast0.Idots(dots,None)))
       |        _ -> k i) in
 
+  let case_line r k e =
+    compute_result Ast0.case_line e
+      (match Ast0.unwrap e with
+       Ast0.DisjCase(starter,case_list,_,ender) ->
+         disj_cases e starter case_list r.VT0.combiner_rec_case_line ender
+      |        _ -> k e) in
+
   let statement r k s =
     compute_result Ast0.stmt s
       (match Ast0.unwrap s with
@@ -403,13 +441,13 @@ let classify is_minus all_marked table code =
        (* cases for everything with extra mcode *)
       |        Ast0.FunDecl((info,bef),_,_,_,_,_,_,_,_)
       | Ast0.Decl((info,bef),_) ->
-         bind (nc_mcode ((),(),info,bef,())) (k s)
+         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,()))
+         bind (k s) (nc_mcode ((),(),info,aft,(),-1))
       |        _ -> k s
 
 ) in
@@ -423,7 +461,7 @@ let classify is_minus all_marked table code =
       (do_nothing Ast0.dotsParam) (do_nothing Ast0.dotsStmt)
       (do_nothing Ast0.dotsDecl) (do_nothing Ast0.dotsCase)
       (do_nothing Ast0.ident) expression typeC initialiser param declaration
-      statement (do_nothing Ast0.case_line) (do_top Ast0.top) in
+      statement case_line (do_top Ast0.top) in
   combiner.VT0.combiner_rec_top_level code
 
 (* --------------------------------------------------------------------- *)
@@ -432,7 +470,7 @@ the same context children *)
 
 (* this is just a sanity check - really only need to look at the top-level
    structure *)
-let equal_mcode (_,_,info1,_,_) (_,_,info2,_,_) =
+let equal_mcode (_,_,info1,_,_,_) (_,_,info2,_,_,_) =
   info1.Ast0.pos_info.Ast0.offset = info2.Ast0.pos_info.Ast0.offset
 
 let equal_option e1 e2 =
@@ -634,8 +672,8 @@ let rec equal_statement s1 s2 =
        equal_mcode rp1 rp2
   | (Ast0.Iterator(nm1,lp1,_,rp1,_,_),Ast0.Iterator(nm2,lp2,_,rp2,_,_)) ->
       equal_mcode lp1 lp2 && equal_mcode rp1 rp2
-  | (Ast0.Switch(switch1,lp1,_,rp1,lb1,case1,rb1),
-     Ast0.Switch(switch2,lp2,_,rp2,lb2,case2,rb2)) ->
+  | (Ast0.Switch(switch1,lp1,_,rp1,lb1,_,_,rb1),
+     Ast0.Switch(switch2,lp2,_,rp2,lb2,_,_,rb2)) ->
        equal_mcode switch1 switch2 && equal_mcode lp1 lp2 &&
        equal_mcode rp1 rp2 && equal_mcode lb1 lb2 &&
        equal_mcode rb1 rb2
@@ -689,6 +727,11 @@ let equal_case_line c1 c2 =
       equal_mcode def1 def2 && equal_mcode colon1 colon2
   | (Ast0.Case(case1,_,colon1,_),Ast0.Case(case2,_,colon2,_)) ->
       equal_mcode case1 case2 && equal_mcode colon1 colon2
+  | (Ast0.DisjCase(starter1,_,mids1,ender1),
+     Ast0.DisjCase(starter2,_,mids2,ender2)) ->
+       equal_mcode starter1 starter2 &&
+       List.for_all2 equal_mcode mids1 mids2 &&
+       equal_mcode ender1 ender2
   | (Ast0.OptCase(_),Ast0.OptCase(_)) -> true
   | _ -> false
 
@@ -839,7 +882,7 @@ let concat = function
                | _ -> failwith "no dots allowed in pure plus code")
            | _ -> failwith "plus code is being discarded") in
       let res =
-       Compute_lines.statement_dots
+       Compute_lines.compute_statement_dots_lines false
          (Ast0.rewrap (List.hd l) (Ast0.DOTS (loop l))) in
       [Ast0.rewrap res (Ast0.CODE res)]
 
@@ -1006,7 +1049,7 @@ let context_neg minus plus =
              classify true
                (function _ -> Ast0.MINUS(ref([],Ast0.default_token_info)))
                minus_table m in
-           let _ = classify false (function _ -> Ast0.PLUS) plus_table p in
+           let _ = classify false (function c -> Ast0.PLUS c) plus_table p in
            traverse minus_table plus_table;
            (m,p)::loop(minus,plus)
          end