Coccinelle release-1.0.0-rc11
[bpt/coccinelle.git] / parsing_cocci / parse_aux.ml
index 31cb8e9..6f300f3 100644 (file)
@@ -1,9 +1,37 @@
+(*
+ * 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.
+ *
+ * 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.
+ *)
+
+
 (* exports everything, used only by parser_cocci_menhir.mly *)
 module Ast0 = Ast0_cocci
 module Ast = Ast_cocci
 
 (* types for metavariable tokens *)
 type info = Ast.meta_name * Ast0.pure * Data.clt
+type midinfo =
+    Ast.meta_name * Data.iconstraints * Ast.seed * 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
@@ -17,7 +45,7 @@ let get_option fn = function
     None -> None
   | Some x -> Some (fn x)
 
-let make_info line logical_line offset col strbef straft =
+let make_info line logical_line offset col strbef straft isSymbol =
   let new_pos_info =
     {Ast0.line_start = line; Ast0.line_end = line;
       Ast0.logical_start = logical_line; Ast0.logical_end = logical_line;
@@ -25,10 +53,11 @@ let make_info line logical_line offset col strbef straft =
   { Ast0.pos_info = new_pos_info;
     Ast0.attachable_start = true; Ast0.attachable_end = true;
     Ast0.mcode_start = []; Ast0.mcode_end = [];
-    Ast0.strings_before = strbef; Ast0.strings_after = straft; }
+    Ast0.strings_before = strbef; Ast0.strings_after = straft;
+    Ast0.isSymbolIdent = isSymbol; }
 
 let clt2info (_,line,logical_line,offset,col,strbef,straft,pos) =
-  make_info line logical_line offset col strbef straft
+  make_info line logical_line offset col strbef straft false
 
 let drop_bef (arity,line,lline,offset,col,strbef,straft,pos) =
   (arity,line,lline,offset,col,[],straft,pos)
@@ -36,44 +65,52 @@ let drop_bef (arity,line,lline,offset,col,strbef,straft,pos) =
 let drop_aft (arity,line,lline,offset,col,strbef,straft,pos) =
   (arity,line,lline,offset,col,strbef,[],pos)
 
+(* used for #define, to put aft on ident/( *)
+let get_aft (arity,line,lline,offset,col,strbef,straft,pos) = straft
+
+let set_aft aft (arity,line,lline,offset,col,strbef,_,pos) =
+  (arity,line,lline,offset,col,strbef,aft,pos)
+
 let drop_pos (arity,line,lline,offset,col,strbef,straft,pos) =
-  (arity,line,lline,offset,col,strbef,straft,Ast0.NoMetaPos)
+  (arity,line,lline,offset,col,strbef,straft,[])
 
-let clt2mcode str = function
+let clt2mcode_ext str isSymbol = function
     (Data.MINUS,line,lline,offset,col,strbef,straft,pos)       ->
-      (str,Ast0.NONE,make_info line lline offset col strbef straft,
-       Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
+      (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
+       Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)),ref pos,-1)
   | (Data.OPTMINUS,line,lline,offset,col,strbef,straft,pos)    ->
-      (str,Ast0.OPT,make_info line lline offset col strbef straft,
-       Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
+      (str,Ast0.OPT,make_info line lline offset col strbef straft isSymbol,
+       Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)),ref pos,-1)
   | (Data.UNIQUEMINUS,line,lline,offset,col,strbef,straft,pos) ->
-      (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
-       Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
+      (str,Ast0.UNIQUE,make_info line lline offset col strbef straft isSymbol,
+       Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)),ref pos,-1)
   | (Data.PLUS,line,lline,offset,col,strbef,straft,pos)        ->
-      (str,Ast0.NONE,make_info line lline offset col strbef straft,
+      (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
        Ast0.PLUS(Ast.ONE),ref pos,-1)
   | (Data.PLUSPLUS,line,lline,offset,col,strbef,straft,pos)        ->
-      (str,Ast0.NONE,make_info line lline offset col strbef straft,
+      (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
        Ast0.PLUS(Ast.MANY),ref pos,-1)
   | (Data.CONTEXT,line,lline,offset,col,strbef,straft,pos)     ->
-      (str,Ast0.NONE,make_info line lline offset col strbef straft,
+      (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
        Ast0.CONTEXT(ref(Ast.NOTHING,
                        Ast0.default_token_info,Ast0.default_token_info)),
        ref pos,-1)
   | (Data.OPT,line,lline,offset,col,strbef,straft,pos)         ->
-      (str,Ast0.OPT,make_info line lline offset col strbef straft,
+      (str,Ast0.OPT,make_info line lline offset col strbef straft isSymbol,
        Ast0.CONTEXT(ref(Ast.NOTHING,
                        Ast0.default_token_info,Ast0.default_token_info)),
        ref pos,-1)
   | (Data.UNIQUE,line,lline,offset,col,strbef,straft,pos)      ->
-      (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
+      (str,Ast0.UNIQUE,make_info line lline offset col strbef straft isSymbol,
        Ast0.CONTEXT(ref(Ast.NOTHING,
                        Ast0.default_token_info,Ast0.default_token_info)),
        ref pos,-1)
 
+let clt2mcode name clt = clt2mcode_ext name false clt
 let id2name   (name, clt) = name
 let id2clt    (name, clt) = clt
 let id2mcode  (name, clt) = clt2mcode name clt
+let sym2mcode (name, clt) = clt2mcode_ext name true clt
 
 let mkdots str (dot,whencode) =
   match str with
@@ -106,6 +143,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))
@@ -149,6 +191,13 @@ 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 first_fn fn first rest =
@@ -176,7 +225,14 @@ let lookup rule name =
        (Semantic_cocci.Semantic("bad rule "^rule^" or bad variable "^name))
 
 let check_meta_tyopt type_irrelevant = function
-    Ast.MetaIdDecl(Ast.NONE,(rule,name)) ->
+    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(_,_) -> ()
       | _ ->
@@ -187,23 +243,30 @@ let check_meta_tyopt type_irrelevant = function
       raise
        (Semantic_cocci.Semantic
           "can't inherit the freshness of an identifier")
-  | Ast.MetaListlenDecl((rule,name)) ->
+  | Ast.MetaTypeDecl(Ast.NONE,(rule,name)) ->
       (match lookup rule name with
-       Ast.MetaListlenDecl(_) -> ()
+       Ast.MetaTypeDecl(_,_) -> ()
       | _ ->
          raise
            (Semantic_cocci.Semantic
               ("incompatible inheritance declaration "^name)))
-  | Ast.MetaTypeDecl(Ast.NONE,(rule,name)) ->
+  | Ast.MetaInitDecl(Ast.NONE,(rule,name)) ->
       (match lookup rule name with
-       Ast.MetaTypeDecl(_,_) -> ()
+       Ast.MetaInitDecl(_,_) -> ()
       | _ ->
          raise
            (Semantic_cocci.Semantic
               ("incompatible inheritance declaration "^name)))
-  | Ast.MetaInitDecl(Ast.NONE,(rule,name)) ->
+  | Ast.MetaInitListDecl(Ast.NONE,(rule,name),len_name) ->
       (match lookup rule name with
-       Ast.MetaInitDecl(_,_) -> ()
+       Ast.MetaInitListDecl(_,_,_) -> ()
+      | _ ->
+         raise
+           (Semantic_cocci.Semantic
+              ("incompatible inheritance declaration "^name)))
+  | Ast.MetaListlenDecl((rule,name)) ->
+      (match lookup rule name with
+       Ast.MetaListlenDecl(_) -> ()
       | _ ->
          raise
            (Semantic_cocci.Semantic
@@ -222,6 +285,13 @@ let check_meta_tyopt type_irrelevant = function
          raise
            (Semantic_cocci.Semantic
               ("incompatible inheritance declaration "^name)))
+  | Ast.MetaConstDecl(Ast.NONE,(rule,name),ty) ->
+      (match lookup rule name with
+       Ast.MetaConstDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
+      | _ ->
+         raise
+           (Semantic_cocci.Semantic
+              ("incompatible inheritance declaration "^name)))
   | Ast.MetaErrDecl(Ast.NONE,(rule,name)) ->
       (match lookup rule name with
        Ast.MetaErrDecl(_,_) -> ()
@@ -258,6 +328,27 @@ let check_meta_tyopt type_irrelevant = function
          raise
            (Semantic_cocci.Semantic
               ("incompatible inheritance declaration "^name)))
+  | Ast.MetaDeclDecl(Ast.NONE,(rule,name)) ->
+      (match lookup rule name with
+       Ast.MetaDeclDecl(_,_) -> ()
+      | _ ->
+         raise
+           (Semantic_cocci.Semantic
+              ("incompatible inheritance declaration "^name)))
+  | Ast.MetaFieldDecl(Ast.NONE,(rule,name)) ->
+      (match lookup rule name with
+       Ast.MetaFieldDecl(_,_) -> ()
+      | _ ->
+         raise
+           (Semantic_cocci.Semantic
+              ("incompatible inheritance declaration "^name)))
+  | Ast.MetaFieldListDecl(Ast.NONE,(rule,name),len_name) ->
+      (match lookup rule name with
+       Ast.MetaFieldListDecl(_,_,_) -> ()
+      | _ ->
+         raise
+           (Semantic_cocci.Semantic
+              ("incompatible inheritance declaration "^name)))
   | Ast.MetaStmDecl(Ast.NONE,(rule,name)) ->
       (match lookup rule name with
        Ast.MetaStmDecl(_,_) -> ()
@@ -286,17 +377,11 @@ let check_meta_tyopt type_irrelevant = function
          raise
            (Semantic_cocci.Semantic
               ("incompatible inheritance declaration "^name)))
-  | Ast.MetaConstDecl(Ast.NONE,(rule,name),ty) ->
-      (match lookup rule name with
-       Ast.MetaConstDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
-      | _ ->
-         raise
-           (Semantic_cocci.Semantic
-              ("incompatible inheritance declaration "^name)))
   | Ast.MetaPosDecl(Ast.NONE,(rule,name)) ->
       (match lookup rule name with
        Ast.MetaPosDecl(_,_) ->
-         if not (List.mem rule !Data.inheritable_positions)
+         if not (List.mem rule !Data.inheritable_positions) &&
+           not !Data.ignore_patch_or_match
          then
            raise
              (Semantic_cocci.Semantic
@@ -414,6 +499,15 @@ 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
   Ast0.wrap(Ast0.MetaStmt(clt2mcode nm clt,pure))
@@ -501,23 +595,44 @@ let make_iso_rule_name_result n =
   Ast.CocciRulename
     (Some n,Ast.NoDep,[],[],Ast.Undetermined,false (*discarded*))
 
+let fix_dependencies d =
+  let rec loop inverted = function
+      Ast0.Dep s when inverted -> Ast.AntiDep s
+    | Ast0.Dep s -> Ast.Dep s
+    | Ast0.AntiDep d -> loop (not inverted) d
+    | Ast0.EverDep s when inverted -> Ast.NeverDep s
+    | Ast0.EverDep s -> Ast.EverDep s
+    | Ast0.NeverDep s when inverted -> Ast.EverDep s
+    | Ast0.NeverDep s -> Ast.NeverDep s
+    | Ast0.AndDep(d1,d2) when inverted ->
+       Ast.OrDep(loop inverted d1,loop inverted d2)
+    | Ast0.AndDep(d1,d2) ->
+       Ast.AndDep(loop inverted d1,loop inverted d2)
+    | Ast0.OrDep(d1,d2) when inverted ->
+       Ast.AndDep(loop inverted d1,loop inverted d2)
+    | Ast0.OrDep(d1,d2) ->
+       Ast.OrDep(loop inverted d1,loop inverted d2)
+    | Ast0.NoDep -> Ast.NoDep
+    | Ast0.FailDep -> Ast.FailDep in
+  loop false d
+
 let make_cocci_rule_name_result nm d i a e ee =
-  Ast.CocciRulename (check_rule_name nm,d,i,a,e,ee)
+  Ast.CocciRulename (check_rule_name nm,fix_dependencies d,i,a,e,ee)
 
 let make_generated_rule_name_result nm d i a e ee =
-  Ast.GeneratedRulename (check_rule_name nm,d,i,a,e,ee)
+  Ast.GeneratedRulename (check_rule_name nm,fix_dependencies d,i,a,e,ee)
 
 let make_script_rule_name_result lang nm deps =
   let l = id2name lang in
-  Ast.ScriptRulename (check_rule_name nm,l,deps)
+  Ast.ScriptRulename (check_rule_name nm,l,fix_dependencies deps)
 
 let make_initial_script_rule_name_result lang deps =
   let l = id2name lang in
-  Ast.InitialScriptRulename(None,l,deps)
+  Ast.InitialScriptRulename(None,l,fix_dependencies deps)
 
 let make_final_script_rule_name_result lang deps =
   let l = id2name lang in
-  Ast.FinalScriptRulename(None,l,deps)
+  Ast.FinalScriptRulename(None,l,fix_dependencies deps)
 
 (* Allows type alone only when it is void and only when there is only one
     parameter.  This avoids ambiguity problems in the parser. *)
@@ -545,3 +660,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 _ | Ast0.MetaInitList _ -> false (* 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"