Release coccinelle-0.2.4
[bpt/coccinelle.git] / parsing_cocci / ast0toast.ml
index e331afe..8539ade 100644 (file)
  *)
 
 
+(*
+ * Copyright 2010, 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.
+ *)
+
+
 (* Arities matter for the minus slice, but not for the plus slice. *)
 
 (* + only allowed on code in a nest (in_nest = true).  ? only allowed on
@@ -31,7 +55,6 @@ module Ast0 = Ast0_cocci
 module Ast = Ast_cocci
 module V0 = Visitor_ast0
 module VT0 = Visitor_ast0_types
-module V = Visitor_ast
 
 let unitary = Type_cocci.Unitary
 
@@ -297,6 +320,36 @@ let dots fn d =
     | Ast0.CIRCLES(x) -> Ast.CIRCLES(List.map fn x)
     | Ast0.STARS(x) -> Ast.STARS(List.map fn x))
 
+(* commas in dotted lists, here due to polymorphism restrictions *)
+
+let add_comma is_comma make_comma itemlist =
+  match Ast0.unwrap itemlist with
+    Ast0.DOTS(x) ->
+      (match List.rev x with
+       [] -> itemlist
+      | e::es ->
+         if is_comma e
+         then itemlist
+         else
+           let comma =
+             match Ast0.get_mcodekind e with
+               Ast0.MINUS(_) -> (Ast0.make_minus_mcode ",")
+             | _ -> (Ast0.make_mcode ",") in
+           Ast0.rewrap itemlist
+             (Ast0.DOTS
+                (List.rev (Ast0.rewrap e (make_comma comma) :: (e::es)))))
+  | _ -> failwith "not possible"
+
+let add_exp_comma =
+  add_comma
+    (function x -> match Ast0.unwrap x with Ast0.EComma _ -> true | _ -> false)
+    (function x -> Ast0.EComma x)
+
+and add_init_comma =
+  add_comma
+    (function x -> match Ast0.unwrap x with Ast0.IComma _ -> true | _ -> false)
+    (function x -> Ast0.IComma x)
+
 (* --------------------------------------------------------------------- *)
 (* Identifier *)
 
@@ -440,7 +493,8 @@ and typeC t =
     | Ast0.BaseType(_) | Ast0.Signed(_,_) | Ast0.Pointer(_,_)
     | Ast0.FunctionPointer(_,_,_,_,_,_,_) | Ast0.FunctionType(_,_,_,_)
     | Ast0.Array(_,_,_,_) | Ast0.EnumName(_,_) | Ast0.StructUnionName(_,_)
-    | Ast0.StructUnionDef(_,_,_,_) | Ast0.TypeName(_) | Ast0.MetaType(_,_) ->
+    | Ast0.StructUnionDef(_,_,_,_) | Ast0.EnumDef(_,_,_,_)
+    | Ast0.TypeName(_) | Ast0.MetaType(_,_) ->
        Ast.Type(None,rewrap t no_isos (base_typeC t))
     | Ast0.DisjType(_,types,_,_) -> Ast.DisjType(List.map typeC types)
     | Ast0.OptType(ty) -> Ast.OptType(typeC ty)
@@ -465,7 +519,10 @@ and base_typeC t =
   | Ast0.Array(ty,lb,size,rb) ->
       Ast.Array(typeC ty,mcode lb,get_option expression size,mcode rb)
   | Ast0.EnumName(kind,name) ->
-      Ast.EnumName(mcode kind,ident name)
+      Ast.EnumName(mcode kind,get_option ident name)
+  | Ast0.EnumDef(ty,lb,ids,rb) ->
+      let ids = add_exp_comma ids in
+      Ast.EnumDef(typeC ty,mcode lb,dots expression ids,mcode rb)
   | Ast0.StructUnionName(kind,name) ->
       Ast.StructUnionName(mcode kind,get_option ident name)
   | Ast0.StructUnionDef(ty,lb,decls,rb) ->
@@ -485,7 +542,9 @@ and base_typeC t =
 and declaration d =
   rewrap d (do_isos (Ast0.get_iso d))
     (match Ast0.unwrap d with
-      Ast0.Init(stg,ty,id,eq,ini,sem) ->
+      Ast0.MetaDecl(name,_) -> Ast.MetaDecl(mcode name,unitary,false)
+    | Ast0.MetaField(name,_) -> Ast.MetaField(mcode name,unitary,false)
+    | Ast0.Init(stg,ty,id,eq,ini,sem) ->
        let stg = get_option mcode stg in
        let ty = typeC ty in
        let id = ident id in
@@ -540,19 +599,32 @@ and strip_idots initlist =
       Ast0.MINUS _ -> true
     | _ -> false in
   match Ast0.unwrap initlist with
-    Ast0.DOTS(x) ->
+    Ast0.DOTS(l) ->
+      let l =
+       match List.rev l with
+         [] | [_] -> l
+       | x::y::xs ->
+           (match (Ast0.unwrap x,Ast0.unwrap y) with
+             (Ast0.IComma _,Ast0.Idots _) ->
+               (* drop comma that was added by add_comma *)
+               List.rev (y::xs)
+           | _ -> l) in
       let (whencode,init,dotinfo) =
-       List.fold_left
-         (function (prevwhen,previnit,dotinfo) ->
-           function cur ->
-             match Ast0.unwrap cur with
+       let rec loop = function
+           [] -> ([],[],[])
+         | x::rest ->
+             (match Ast0.unwrap x with
                Ast0.Idots(dots,Some whencode) ->
-                 (whencode :: prevwhen, previnit,
+                 let (restwhen,restinit,dotinfo) = loop rest in
+                 (whencode :: restwhen, restinit,
                    (isminus dots)::dotinfo)
-             | Ast0.Idots(dots,None) ->
-                 (prevwhen, previnit, (isminus dots)::dotinfo)
-             | _ -> (prevwhen, cur :: previnit, dotinfo))
-         ([],[],[]) x in
+             | Ast0.Idots(dots,None) ->
+                 let (restwhen,restinit,dotinfo) = loop rest in
+                 (restwhen, restinit, (isminus dots)::dotinfo)
+             | _ -> 
+                 let (restwhen,restinit,dotinfo) = loop rest in
+                 (restwhen,x::restinit,dotinfo)) in
+       loop l in
       let allminus =
        if List.for_all (function x -> not x) dotinfo
        then false (* false if no dots *)
@@ -560,7 +632,7 @@ and strip_idots initlist =
          if List.for_all (function x -> x) dotinfo
          then true
          else failwith "inconsistent annotations on initialiser list dots" in
-      (List.rev whencode, List.rev init, allminus)
+      (whencode, init, allminus)
   | Ast0.CIRCLES(x) | Ast0.STARS(x) -> failwith "not possible for an initlist"
 
 and initialiser i =
@@ -568,17 +640,25 @@ and initialiser i =
     (match Ast0.unwrap i with
       Ast0.MetaInit(name,_) -> Ast.MetaInit(mcode name,unitary,false)
     | Ast0.InitExpr(exp) -> Ast.InitExpr(expression exp)
-    | Ast0.InitList(lb,initlist,rb) ->
+    | Ast0.InitList(lb,initlist,rb,true) ->
+       let initlist = add_init_comma initlist in
+       Ast.ArInitList(mcode lb,dots initialiser initlist,mcode rb)
+    | Ast0.InitList(lb,initlist,rb,false) ->
+       let initlist = add_init_comma initlist in
        let (whencode,initlist,allminus) = strip_idots initlist in
-       Ast.InitList(allminus,mcode lb,List.map initialiser initlist,mcode rb,
-                    List.map initialiser whencode)
+       Ast.StrInitList
+         (allminus,mcode lb,List.map initialiser initlist,mcode rb,
+          List.map initialiser whencode)
     | Ast0.InitGccExt(designators,eq,ini) ->
        Ast.InitGccExt(List.map designator designators,mcode eq,
                       initialiser ini)
     | Ast0.InitGccName(name,eq,ini) ->
        Ast.InitGccName(ident name,mcode eq,initialiser ini)
     | Ast0.IComma(comma) -> Ast.IComma(mcode comma)
-    | Ast0.Idots(_,_) -> failwith "Idots should have been removed"
+    | Ast0.Idots(dots,whencode) ->
+       let dots = mcode dots in
+       let whencode = get_option initialiser whencode in
+       Ast.Idots(dots,whencode)
     | Ast0.OptIni(ini) -> Ast.OptIni(initialiser ini)
     | Ast0.UniqueIni(ini) -> Ast.UniqueIni(initialiser ini))