Release coccinelle-0.2.0
[bpt/coccinelle.git] / parsing_cocci / single_statement.ml
index 4209f2f..ce72644 100644 (file)
@@ -1,23 +1,23 @@
 (*
-* 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-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
@@ -45,7 +45,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
@@ -55,7 +55,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
@@ -74,14 +74,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.StatementTag(s)]],ti) ->
          (match Ast.unwrap s with
            Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
-         | _ -> false)
+         | _ -> mc := ([[Ast.StatementTag(s)]],ti); false)
       |        (_,_) -> true)
   | Ast0.CONTEXT mc | Ast0.MIXED mc ->
       (match !mc with
@@ -91,15 +91,16 @@ 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.StatementTag(s)]],ti) ->
          (match Ast.unwrap s with
            Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
-         | _ -> false)
-      |        (l,_) -> any_statements l)
+         | _ -> mc := ([[Ast.StatementTag(s)]],ti); false)
+      |        (l,_) when any_statements l -> true
+      |        (l,ti) -> mc := (l,ti); false)
   | Ast0.CONTEXT mc | Ast0.MIXED mc ->
       (match !mc with
        (Ast.AFTER _,_,_) -> true
@@ -227,7 +228,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
@@ -267,7 +269,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
@@ -303,10 +305,10 @@ 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.StatementTag(s)]],ti) ->
          (match Ast.unwrap s with
            Ast.IfThen(_,_,_) -> true (* potentially dangerous *)
-         | _ -> false)
+         | _ -> mc := ([[Ast.StatementTag(s)]],ti); false)
       |        (_,_) -> true)
   | Ast0.CONTEXT(mc) ->
       let (text,tinfo1,tinfo2) = !mc in
@@ -327,7 +329,7 @@ and contains_only_minus =
        | _ -> 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
 
@@ -364,11 +366,18 @@ and contains_only_minus =
        List.for_all r.VT0.combiner_rec_statement_dots statement_dots_list
     | _ -> k e in
 
+  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
     dots dots dots dots dots dots
     donothing expression typeC donothing donothing declaration
-    statement donothing donothing
+    statement case_line donothing
 
 
 (* needs a special case when there is a Disj or an empty DOTS *)
@@ -398,32 +407,44 @@ let add_braces orig_s =
     | 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
 
 (* ---------------------------------------------------------------------- *)
 
@@ -519,12 +540,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
@@ -565,6 +587,8 @@ 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