Coccinelle release-1.0.0-rc11
[bpt/coccinelle.git] / parsing_cocci / top_level.ml
index dea5573..aff803c 100644 (file)
@@ -1,4 +1,8 @@
 (*
+ * 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.
@@ -43,56 +47,76 @@ let top_dots l =
   then Ast0.wrap (Ast0.STARS(l))
   else Ast0.wrap (Ast0.DOTS(l))
 
-let scan_code l =
-  let statements = ref false in
+let rec is_decl s =
+  match Ast0.unwrap s with
+    Ast0.Decl(_,e) -> true
+  | _ -> false
+
+let isonly f l = match Ast0.undots l with [s] -> f s | _ -> false
+let isall f l = List.for_all (isonly f) l
+
+let rec is_toplevel s =
+  match Ast0.unwrap s with
+    Ast0.Decl(_,e) -> true
+  | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
+  | Ast0.Disj(_,stmts,_,_) -> isall is_toplevel stmts
+  | Ast0.ExprStatement(Some fc,_) -> false
+  | Ast0.Include(_,_) -> true
+  | Ast0.Undef(_,_) -> true
+  | Ast0.Define(_,_,_,_) -> true
+  | _ -> false
+
+let scan_code must_be_code l =
   let rec loop = function
       [] -> ([],[])
     | (x::xs) as all ->
-       (match Ast0.unwrap x with
-         (Ast0.OTHER(code)) ->
-           (match Ast0.unwrap code with
-             Ast0.Decl(_) ->
-               let (front,rest) = loop xs in
-               (code::front,rest)
-           | _ ->
-               statements := true;
-               let (front,rest) = loop xs in
-               (code::front,rest))
-       | _ -> ([],all)) in
+        (match Ast0.unwrap x with
+          (Ast0.OTHER(code)) ->
+            let (front,rest) = loop xs in
+            (code::front,rest)
+        | _ -> ([],all)) in
   match loop l with
     ([],_) as res -> res
   | (code,rest) ->
-      if !statements = true
-      then ([Ast0.wrap(Ast0.CODE(top_dots code))],rest)
-      else
-       (List.map
-          (function d ->
-            match Ast0.unwrap d with
-              Ast0.Decl(bef,x) -> Ast0.wrap (Ast0.DECL(d))
-            | _ -> failwith "impossible")
-          code,
-        rest)
+      (match code with
+      | [x] when is_decl x && must_be_code ->
+         ([Ast0.wrap(Ast0.NONDECL x)],rest)
+      | _ when List.for_all is_toplevel code ->
+         ([Ast0.wrap(Ast0.TOPCODE(top_dots code))],rest)
+      | _ ->
+         ([Ast0.wrap(Ast0.CODE(top_dots code))],rest))
 
 let rec scan_top_decl = function
     [] -> ([],[])
   | ((topdecl::rest) as all) ->
       (match Ast0.unwrap topdecl with
        Ast0.OTHER(_) -> ([],all)
-      | _ -> let (front,rest) = scan_top_decl rest in (topdecl::front,rest))
+      | _ ->
+         let (front,rest) = scan_top_decl rest
+         in (topdecl::front,rest))
 
 (* for debugging *)
 let l2c l =
   match Ast0.unwrap l with
-    Ast0.DECL(_) -> "decl"
+    Ast0.NONDECL(_) -> "decl"
   | Ast0.CODE(_) -> "code"
+  | Ast0.TOPCODE(_) -> "code"
   | Ast0.FILEINFO(_,_) -> "fileinfo"
   | Ast0.ERRORWORDS(_) -> "errorwords"
   | Ast0.OTHER(_) -> "other"
 
-let rec top_level l =
-  match scan_code l with
+let rec top_level must_be_code l =
+  match scan_code must_be_code l with
     (code,[]) -> code
   | (code,rest) ->
       (match scan_top_decl rest with
        (top_decls,[]) -> code@top_decls
-      |        (top_decls,rest) -> code @ top_decls @ (top_level rest))
+      |        (top_decls,rest) -> code @ top_decls @ (top_level must_be_code rest))
+
+let clean l =
+  List.map
+    (function tl ->
+      match Ast0.unwrap tl with
+       Ast0.TOPCODE x -> Ast0.rewrap tl (Ast0.CODE x)
+      |        _ -> tl)
+    l