Coccinelle release 0.2.5-rc8
[bpt/coccinelle.git] / parsing_cocci / parse_aux.ml
index 2dead52..a4a4373 100644 (file)
@@ -1,4 +1,6 @@
 (*
+ * 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.
@@ -29,13 +31,12 @@ type info = Ast.meta_name * Ast0.pure * Data.clt
 type idinfo = Ast.meta_name * Data.iconstraints * Ast0.pure * Data.clt
 type expinfo = Ast.meta_name * Data.econstraints * Ast0.pure * Data.clt
 type tyinfo = Ast.meta_name * Ast0.typeC list * Ast0.pure * Data.clt
-type list_info = Ast.meta_name * Ast.meta_name option * Ast0.pure * Data.clt
+type list_info = Ast.meta_name * Ast.list_len * Ast0.pure * Data.clt
 type typed_expinfo =
     Ast.meta_name * Data.econstraints * Ast0.pure *
       Type_cocci.typeC list option * Data.clt
 type pos_info = Ast.meta_name * Data.pconstraints * Ast.meta_collect * Data.clt
 
-
 let get_option fn = function
     None -> None
   | Some x -> Some (fn x)
@@ -129,6 +130,11 @@ let mkddots str (dot,whencode) =
   | ("...",Some [w]) -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, Some w))
   | _ -> failwith "cannot happen"
 
+let mkddots_one str (dot,whencode) =
+  match str with
+    "..." -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, whencode))
+  | _ -> failwith "cannot happen"
+
 let mkpdots str dot =
   match str with
     "..." -> Ast0.wrap(Ast0.Pdots(clt2mcode str dot))
@@ -172,9 +178,16 @@ let ty_pointerify ty m =
     (function inner -> function cur -> Type_cocci.Pointer(inner))
     ty m
 
+let arrayify ty ar =
+  List.fold_right
+    (function (l,i,r) ->
+      function rest ->
+       Ast0.wrap (Ast0.Array(rest,clt2mcode "[" l,i,clt2mcode "]" r)))
+    ar ty
+
 (* Left is <=>, Right is =>.  Collect <=>s. *)
 (* The parser should have done this, with precedences.  But whatever... *)
-let iso_adjust fn first rest =
+let iso_adjust first_fn fn first rest =
   let rec loop = function
       [] -> [[]]
     | (Common.Left x)::rest ->
@@ -186,21 +199,27 @@ let iso_adjust fn first rest =
          front::after -> []::(fn x::front)::after
        | _ -> failwith "not possible") in
   match loop rest with
-    front::after -> (fn first::front)::after
+    front::after -> (first_fn first::front)::after
   | _ -> failwith "not possible"
 
-let check_meta tok =
-  let lookup rule name =
-    try
-      let info = Hashtbl.find Data.all_metadecls rule in
-      List.find (function mv -> Ast.get_meta_name mv = (rule,name)) info
-    with
-      Not_found ->
-       raise
-         (Semantic_cocci.Semantic
-            ("bad rule "^rule^" or bad variable "^name)) in
-  match tok with
-    Ast.MetaIdDecl(Ast.NONE,(rule,name)) ->
+let lookup rule name =
+  try
+    let info = Hashtbl.find Data.all_metadecls rule in
+    List.find (function mv -> Ast.get_meta_name mv = (rule,name)) info
+  with
+    Not_found ->
+      raise
+       (Semantic_cocci.Semantic("bad rule "^rule^" or bad variable "^name))
+
+let check_meta_tyopt type_irrelevant = function
+    Ast.MetaMetaDecl(Ast.NONE,(rule,name)) ->
+      (match lookup rule name with
+       Ast.MetaMetaDecl(_,_) -> ()
+      | _ ->
+         raise
+           (Semantic_cocci.Semantic
+              ("incompatible inheritance declaration "^name)))
+  | Ast.MetaIdDecl(Ast.NONE,(rule,name)) ->
       (match lookup rule name with
        Ast.MetaIdDecl(_,_) | Ast.MetaFreshIdDecl(_,_) -> ()
       | _ ->
@@ -255,21 +274,21 @@ let check_meta tok =
               ("incompatible inheritance declaration "^name)))
   | Ast.MetaExpDecl(Ast.NONE,(rule,name),ty) ->
       (match lookup rule name with
-       Ast.MetaExpDecl(_,_,ty1) when ty = ty1 -> ()
+       Ast.MetaExpDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
       | _ ->
          raise
            (Semantic_cocci.Semantic
               ("incompatible inheritance declaration "^name)))
   | Ast.MetaIdExpDecl(Ast.NONE,(rule,name),ty) ->
       (match lookup rule name with
-       Ast.MetaIdExpDecl(_,_,ty1) when ty = ty1 -> ()
+       Ast.MetaIdExpDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
       | _ ->
          raise
            (Semantic_cocci.Semantic
               ("incompatible inheritance declaration "^name)))
   | Ast.MetaLocalIdExpDecl(Ast.NONE,(rule,name),ty) ->
       (match lookup rule name with
-       Ast.MetaLocalIdExpDecl(_,_,ty1) when ty = ty1 -> ()
+       Ast.MetaLocalIdExpDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
       | _ ->
          raise
            (Semantic_cocci.Semantic
@@ -312,7 +331,7 @@ let check_meta tok =
               ("incompatible inheritance declaration "^name)))
   | Ast.MetaConstDecl(Ast.NONE,(rule,name),ty) ->
       (match lookup rule name with
-       Ast.MetaConstDecl(_,_,ty1) when ty = ty1 -> ()
+       Ast.MetaConstDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
       | _ ->
          raise
            (Semantic_cocci.Semantic
@@ -333,6 +352,16 @@ let check_meta tok =
       raise
        (Semantic_cocci.Semantic ("arity not allowed on imported declaration"))
 
+let check_meta m = check_meta_tyopt false m
+
+let check_inherited_constraint meta_name fn =
+  match meta_name with
+    (None,_) -> failwith "constraint must be an inherited variable"
+  | (Some rule,name) ->
+      let i = (rule,name) in
+      check_meta_tyopt true (fn i);
+      i
+
 let create_metadec ar ispure kindfn ids current_rule =
   List.concat
     (List.map
@@ -346,6 +375,15 @@ let create_metadec ar ispure kindfn ids current_rule =
         kindfn ar rule ispure checker)
        ids)
 
+
+let create_metadec_virt ar ispure kindfn ids current_rule =
+  List.concat
+    (List.map
+       (function nm ->
+        let checker = function x -> [Common.Right x] in
+        kindfn ar nm ispure checker !Flag.defined_virtual_env)
+       ids)
+
 let create_fresh_metadec kindfn ids current_rule =
   List.concat
     (List.map
@@ -386,15 +424,20 @@ let create_metadec_ty ar ispure kindfn ids current_rule =
        ids)
 
 let create_len_metadec ar ispure kindfn lenid ids current_rule =
-  let lendec =
-    create_metadec Ast.NONE Ast0.Impure
-      (fun _ name _ check_meta -> check_meta(Ast.MetaListlenDecl(name)))
-      [lenid] current_rule in
-  let lenname =
-    match lendec with
-      [Common.Left (Ast.MetaListlenDecl(x))] -> x
-    | [Common.Right (Ast.MetaListlenDecl(x))] -> x
-    | _ -> failwith "unexpected length declaration" in
+  let (lendec,lenname) =
+    match lenid with
+      Common.Left lenid ->
+       let lendec =
+         create_metadec Ast.NONE Ast0.Impure
+           (fun _ name _ check_meta -> check_meta(Ast.MetaListlenDecl(name)))
+           [lenid] current_rule in
+       let lenname =
+         match lendec with
+           [Common.Left (Ast.MetaListlenDecl(x))] -> Ast.MetaLen x
+         | [Common.Right (Ast.MetaListlenDecl(x))] -> Ast.MetaLen x
+         | _ -> failwith "unexpected length declaration" in
+       (lendec,lenname)
+    | Common.Right n -> ([],Ast.CstLen n) in
   lendec@(create_metadec ar ispure (kindfn lenname) ids current_rule)
 
 (* ---------------------------------------------------------------------- *)
@@ -404,7 +447,24 @@ let str2inc s =
   List.map (function "..." -> Ast.IncDots | s -> Ast.IncPath s) elements
 
 (* ---------------------------------------------------------------------- *)
-(* statements *)
+(* declarations and statements *)
+
+let meta_decl name =
+  let (nm,pure,clt) = name in
+  Ast0.wrap(Ast0.MetaDecl(clt2mcode nm clt,pure))
+
+let meta_field name =
+  let (nm,pure,clt) = name in
+  Ast0.wrap(Ast0.MetaField(clt2mcode nm clt,pure))
+
+let meta_field_list name =
+  let (nm,lenname,pure,clt) = name in
+  let lenname =
+    match lenname with
+      Ast.AnyLen -> Ast0.AnyListLen
+    | Ast.MetaLen nm -> Ast0.MetaListLen(clt2mcode nm clt)
+    | Ast.CstLen n -> Ast0.CstListLen n in
+  Ast0.wrap(Ast0.MetaFieldList(clt2mcode nm clt,lenname,pure))
 
 let meta_stm name =
   let (nm,pure,clt) = name in
@@ -478,43 +538,38 @@ let seq lb s rb =
 
 (* ---------------------------------------------------------------------- *)
 
-let make_iso_rule_name_result n =
-    (try let _ =  Hashtbl.find Data.all_metadecls n in
-    raise (Semantic_cocci.Semantic ("repeated rule name"))
-    with Not_found -> ());
-    Ast.CocciRulename (Some n,Ast.NoDep,[],[],Ast.Undetermined,false (*discarded*))
-
-let make_cocci_rule_name_result nm d i a e ee =
-  match nm with
+let check_rule_name = function
     Some nm ->
       let n = id2name nm in
       (try let _ =  Hashtbl.find Data.all_metadecls n in
       raise (Semantic_cocci.Semantic ("repeated rule name"))
-      with Not_found -> ());
-      Ast.CocciRulename (Some n,d,i,a,e,ee)
-  | None -> Ast.CocciRulename (None,d,i,a,e,ee)
+      with Not_found -> Some n)
+  | None -> None
+
+let make_iso_rule_name_result n =
+  (try let _ =  Hashtbl.find Data.all_metadecls n in
+  raise (Semantic_cocci.Semantic ("repeated rule name"))
+  with Not_found -> ());
+  Ast.CocciRulename
+    (Some n,Ast.NoDep,[],[],Ast.Undetermined,false (*discarded*))
+
+let make_cocci_rule_name_result nm d i a e ee =
+  Ast.CocciRulename (check_rule_name nm,d,i,a,e,ee)
 
 let make_generated_rule_name_result nm d i a e ee =
-  match nm with
-    Some nm ->
-      let n = id2name nm in
-      (try let _ =  Hashtbl.find Data.all_metadecls n in
-      raise (Semantic_cocci.Semantic ("repeated rule name"))
-      with Not_found -> ());
-      Ast.GeneratedRulename (Some n,d,i,a,e,ee)
-  | None -> Ast.GeneratedRulename (None,d,i,a,e,ee)
+  Ast.GeneratedRulename (check_rule_name nm,d,i,a,e,ee)
 
-let make_script_rule_name_result lang deps =
+let make_script_rule_name_result lang nm deps =
   let l = id2name lang in
-  Ast.ScriptRulename (l,deps)
+  Ast.ScriptRulename (check_rule_name nm,l,deps)
 
-let make_initial_script_rule_name_result lang =
+let make_initial_script_rule_name_result lang deps =
   let l = id2name lang in
-  Ast.InitialScriptRulename(l)
+  Ast.InitialScriptRulename(None,l,deps)
 
-let make_final_script_rule_name_result lang =
+let make_final_script_rule_name_result lang deps =
   let l = id2name lang in
-  Ast.FinalScriptRulename(l)
+  Ast.FinalScriptRulename(None,l,deps)
 
 (* Allows type alone only when it is void and only when there is only one
     parameter.  This avoids ambiguity problems in the parser. *)
@@ -542,3 +597,30 @@ let verify_parameter_declarations = function
                   (Ast0.get_line t))
          | _ -> ())
        l
+
+(* ---------------------------------------------------------------------- *)
+(* decide whether an init list is ordered or unordered *)
+
+let struct_initializer initlist =
+  let rec loop i =
+    match Ast0.unwrap i with
+      Ast0.InitGccExt _ -> true
+    | Ast0.InitGccName _ -> true
+    | Ast0.OptIni i | Ast0.UniqueIni i -> loop i
+    | Ast0.MetaInit _ -> true (* ambiguous... *)
+    | _ -> false in
+  let l = Ast0.undots initlist in
+  (l = []) or (List.exists loop l)
+
+let drop_dot_commas initlist =
+  match Ast0.unwrap initlist with
+    Ast0.DOTS(l) ->
+      let rec loop after_comma = function
+         [] -> []
+       | x::xs ->
+           (match Ast0.unwrap x with
+             Ast0.Idots(dots,whencode) -> x :: (loop true xs)
+           | Ast0.IComma(comma) when after_comma -> (*drop*) loop false xs
+           | _ -> x :: (loop false xs)) in
+      Ast0.rewrap initlist (Ast0.DOTS(loop false l))
+  | _ -> failwith "not supported"